http://acm.sdibt.edu.cn/JudgeOnline/problem.php?id=3232
It's easy for ACMer to calculate A^X mod P. Now given seven integers n, A, K, a, b, m, P, and a function f(x) which defined as following.
f(x) = K, x = 1
f(x) = (a*f(x-1) + b)%m , x > 1
Now, Your task is to calculate
( A^(f(1)) + A^(f(2)) + A^(f(3)) + ...... + A^(f(n)) ) modular P.
In the first line there is an integer T (1 < T <= 40), which indicates the number of test cases, and then T test cases follow. A test case contains seven integers n, A, K, a, b, m, P in one line.
1 <= n <= 10^6
0 <= A, K, a, b <= 10^9
1 <= m, P <= 10^9
For each case, the output format is “Case #c: ans”.
c is the case number start from 1.
ans is the answer of this problem.
2 3 2 1 1 1 100 100 3 15 123 2 3 1000 107
Case #1: 14 Case #2: 63
和昨天做的福大的很像,但不是。
题目意思很简单,比赛用了枚举的方法,知道会超时,40组测试数据。
时间复杂度 o(n)=10^6*40*logn ==>10^9 每计算一个a^p%m logn
怎么做?
( A^(f(1)) + A^(f(2)) + A^(f(3)) + ...... + A^(f(n)) ) modular P.
看来别人的思路,才想到拆分。有了这个思想,就容易起来了,就是哈希。保存结果,每一次遇到,直接读取。避免了重复计算。
A^n=A^(k*x+y);
n=k*x+y;==>(A^k)^x * A^y;
A^k和A^y可以用一个dp1[ ]数组保存起来。这样就解决一个了。
(A^k)^x也用一个数组 dp2[ ]保存起来。
式子就可以转化为 A^n= dp2[n/k]*dp1[n%k]; 对比一下 (A^k)^x * A^y;
K取多大呢???10^6? 太大了,超了,没有必要这么大。
因为:
f(x) = (a*f(x-1) + b)%m , x > 1
f(x)最大是10^9 所以K=33333就足够了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #define HH 33000 6 #define GG 33000 7 using namespace std; 8 9 10 long long dp1[1000003]; 11 long long dp2[1000003]; 12 13 void make_ini(long long A,long long P) 14 { 15 long long i; 16 dp1[0]=dp2[0]=1; 17 dp1[1]=A; 18 for(i=2;i<=HH;i++) 19 dp1[i]=(dp1[i-1]*A)%P;//A^k 20 21 dp2[1]=dp1[HH]; 22 for(i=2;i<=GG;i++) 23 dp2[i]=(dp1[HH]*dp2[i-1])%P; 24 } 25 26 long long make_then(long long K,long long n,long long A,long long a,long long b,long long m,long long P) 27 { 28 long long ans=0,i,j,tmp; 29 tmp=K; 30 for(i=1;i<=n;i++) 31 { 32 ans=(ans+dp2[tmp/HH]*dp1[tmp%HH])%P; 33 tmp=(a*tmp+b)%m; 34 } 35 return ans; 36 } 37 38 39 int main() 40 { 41 long long T,n,A,K,a,b,m,P,i,tmp; 42 while(scanf("%lld",&T)>0) 43 { 44 for(i=1;i<=T;i++) 45 { 46 scanf("%lld%lld%lld%lld%lld%lld%lld",&n,&A,&K,&a,&b,&m,&P); 47 make_ini(A,P); 48 tmp=make_then(K,n,A,a,b,m,P); 49 printf("Case #%lld: %lld\n",i,tmp); 50 } 51 } 52 return 0; 53 }