山东第四届省赛C题: A^X mod P

时间:2021-04-15 00:27:34

http://acm.sdibt.edu.cn/JudgeOnline/problem.php?id=3232

Problem C:A^X mod P

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 10  Solved: 2
[Submit][Status][Discuss]

Description

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.

Input

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

Output

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.

Sample Input

2
3 2 1 1 1 100 100
3 15 123 2 3 1000 107

Sample Output

Case #1: 14
Case #2: 63

HINT

Source

山东省第四届ACM程序设计大赛2013.6.9

和昨天做的福大的很像,但不是。

题目意思很简单,比赛用了枚举的方法,知道会超时,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就足够了。

 #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define HH 33000
#define GG 33000
using namespace std; long long dp1[];
long long dp2[]; void make_ini(long long A,long long P)
{
long long i;
dp1[]=dp2[]=;
dp1[]=A;
for(i=;i<=HH;i++)
dp1[i]=(dp1[i-]*A)%P;//A^k dp2[]=dp1[HH];
for(i=;i<=GG;i++)
dp2[i]=(dp1[HH]*dp2[i-])%P;
} 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)
{
long long ans=,i,j,tmp;
tmp=K;
for(i=;i<=n;i++)
{
ans=(ans+dp2[tmp/HH]*dp1[tmp%HH])%P;
tmp=(a*tmp+b)%m;
}
return ans;
} int main()
{
long long T,n,A,K,a,b,m,P,i,tmp;
while(scanf("%lld",&T)>)
{
for(i=;i<=T;i++)
{
scanf("%lld%lld%lld%lld%lld%lld%lld",&n,&A,&K,&a,&b,&m,&P);
make_ini(A,P);
tmp=make_then(K,n,A,a,b,m,P);
printf("Case #%lld: %lld\n",i,tmp);
}
}
return ;
}