标签:tin amp 元组 turn 就会 mod 注意 loss int
题意
输入两个非负整数a,b和正整数n(0<=a,b<2^64,1<=n<=1000),你的任务是计算f(a^b)除以n的余数。其中f[0] =0,f[1] = 1,且对于所有的非负整数i,f(i+2) = f(i+1) +f(i)。
分析
所有计算都是对n取模的,不妨设F[i] = f[i]%n。不难发现,当二元组(f[i],f[i+1])出现重复时,整个序列就开始重复。为什么呢?是由递推序列的性质决定的,f(i+2) = f(i+1) +f(i)。例如,n=3,序列F[i]的前10项为1,1,2,0,2,2,1,0,1,1,第9,10项和前两项完全一样。根据递推公式,第11项会等于第3项,第12项等于第4项......多久会出现重复呢?因为余数最多有n种,所以最多n^2项就会出现重复。设周期为M,则只需计算出F[0]~F[n^2],然后计算出F(a^b)等于其中的哪一项即可。
代码实现
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll; //此题会爆long long
const int maxn = 1e6+5;
int f[maxn];
ll ksm(ll a, ll b,int mod){
ll ans = 1;
while(b){
if(b&1)
ans = ans*a%mod;
a = a*a%mod;
b = b>>1;
}
return ans%mod;
}
int main(void)
{
int t;
cin >> t;
while(t--)
{
ll a,b;
int n;
cin >> a >> b >> n;
if(a==0||n==1){
cout<<0<<endl;
continue;
}
int T = 0;
f[0] = 0;
f[1] = 1;
for(int i = 2; i <= n*n; i++){
f[i] = (f[i-1]+f[i-2])%n;
if(f[i]==f[1]&&f[i-1]==f[0]){
T = i-1;
break;
}
}
int k = ksm(a%T,b,T);
cout<<f[k]<<endl;
}
return 0;
}
总结
取模的时候,特别注意一下1和0这种情况。
标签:tin amp 元组 turn 就会 mod 注意 loss int
原文地址:https://www.cnblogs.com/AC-AC/p/12316663.html