JZOJ 1351. 阅读程序写结果

题目

Description

  NOIP2009普及组初赛阅读程序第三题如下:
  const c = 2009; 
  var 
   n, p, s, i, j, t: integer; 
  begin 
   read(n, p); 
   s := 0; 
   t := 1; 
   for i := 1 to n do 
   begin 
   t := t * p mod c; 
   for j := 1 to i do 
   s := (s + t) mod c; 
   end; 
   writeln(s); 
  end. 
  输入:11 2
  输出:______
  这题很简单,死做都能做出来,但如果扩大N的范围,你还能做吗?
 

Input

  输入N(1<=N<=10^1000),P(1<=P<=1000),之间用一个空格隔开。

Output

  输出结果。
 

Sample Input

11 2

Sample Output

782
 

Data Constraint

 
 

Hint

【数据规模】
  50%的N<=1,000,000

 

分析

 

 

  • 首先我们可以知道
  • $\sum_{i=1}^{n}\qquad q^i*q $这个就是我们要求的
  • 直接算有50
  • 我们考虑用矩阵快速幂优化
  • 设矩阵为$[p^i,p^i*i,sum[i-1]]$
  • 我们推得$p^(i+1)*(i+1)=p^i*p+p^i*p
  • 我们列出矩阵
  • | p  p  0 |
  • | 0  p  1 |
  • | 0  0  1 |
  • 乘出来就好了
  • 因为只有一行
  • 每一次都乘一列加起来

 

代码

 

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
const int mo = 2009;
using namespace std;
int h[1020],cnt;
struct sb
{
    int a[3][3];
};
sb x;
int ans[3];
bool check()
{
    for (int i=1;i<=1000;i++)
      if (h[i]!=0) return false;
    return true;
}
sb mul(sb x,sb y)
{
    sb res;
    memset(res.a,0,sizeof(res));
    for (int i=0;i<3;i++)
      for (int j=0;j<3;j++)
        for (int k=0;k<3;k++)
         res.a[i][j]=(res.a[i][j]+x.a[i][k]*y.a[k][j])%mo;
    return res;
}
void mull() 
{
    ll c[3];memset(c,0,sizeof(c));
    for(ll i=0;i<=2;i++)for(ll j=0;j<=2;j++)c[i]=(c[i]+x.a[j][i]*ans[j]%mo)%mo;
    for (int i=0;i<=2;i++) ans[i]=c[i];
}
void div()
{
    int wz=1;
    while (h[wz]==0) wz++;
    int r=0,t;
    for (int i=wz;i<=cnt;i++)
    {
        t=h[i];
        h[i]=(r*10+h[i])/2;
        r=(r*10+t)%2;
    }
}
int main()
{
    char c;
    c=getchar();
    while (c!=' ')
    {
        h[++cnt]=c-'0';
        c=getchar();
    }
    int p;
    cin>>p; 
    memset(x.a,0,sizeof(x));
    ans[0]=ans[1]=p;
    x.a[0][0]=p; x.a[0][1]=p; x.a[1][1]=p; x.a[1][2]=1; x.a[2][2]=1;
    while (!check())
    {
        if (h[cnt]&1!=0) mull();
        x=mul(x,x);
        div();
    }
    cout<<ans[2];
    return 0;
}

 

 

posted @ 2019-11-06 15:22  Melted_czj  阅读(146)  评论(0编辑  收藏  举报
body { background-color:whitesmoke; } // 修改背景颜色为半透明 #home,#sideBarMain>div,#blog-sidecolumn>div>div,.catListView{ background-color:rgba(255,255,255,0); } // 修改其他边框的颜色