您的位置:首页 > 其它

uva11582 斐波拉切数列循环节+欧拉定理降幂

2016-07-10 12:40 344 查看
The i’th Fibonacci number f(i) is

recursively defined in the following

way:

• f(0) = 0 and f(1) = 1

• f(i + 2) = f(i + 1) + f(i) for

every i ≥ 0

Your task is to compute some

values of this sequence.

Input

Input begins with an integer t ≤

10, 000, the number of test cases.

Each test case consists of three integers

a, b, n where 0 ≤ a, b < 2

64

(a and b will not both be zero) and

1 ≤ n ≤ 1000.

Output

For each test case, output a single line containing the remainder of f(a

b

) upon division by n.

Sample Input

3

1 1 2

2 3 1000

18446744073709551615 18446744073709551615 1000

Sample Output

1

21

250

题目意思:

给a,b,n三个数,求f(a^b)%n

a,b最大值2^64-1,用unsigned long long n=1000

思路:

打表找出每个n的循环节及其长度,降下幂(不降也行)。

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;

#define ull unsigned long long
const int MAX_N=1005;
int euler[MAX_N<<4];//注意这里要降幂的话求的是循环节长度的欧拉函数,大于1005
void euler_init(){
int i,j;
euler[1]=1;
for(i=2;i<MAX_N<<4;i++)
euler[i]=i;
for(i=2;i<MAX_N<<4;i++)
if(euler[i]==i)
for(j=i;j<MAX_N<<4;j+=i)
euler[j]=euler[j]/i*(i-1);
}
int quickpowmod(ull x,ull y, int mod)
{
int ret = 1;
while(y){
if(y&1)
ret = ret*x%mod;
x = x*x%mod;
y >>= 1;
}
return ret;
}
int g[MAX_N];
int f[MAX_N][MAX_N<<4];//循环节长度要大于1005,因为是两个相同(最差应该是MAX_N的平方,但开不了这么大)
ull a,b;
int T,ans,n;

void get_gf(){//找到循环节
for(int i=2;i<MAX_N;i++){
f[i][0]=0;
f[i][1]=1;
for(int j=2;;j++){
f[i][j]=(f[i][j-1]+f[i][j-2])%i;
if(f[i][j-1]==0&&f[i][j]==1){
g[i]=j-1;
break;
}
}
}
}

int main()
{
euler_init();
get_gf();
scanf("%d",&T);
while(T--){
scanf("%llu%llu%d",&a,&b,&n);
if(a==0||n==1)cout<<0<<endl;
else {
int a1=a%g
;
int b1;
if(b<euler[g
])b1=b;//降下幂
else {
b1=b%euler[g
]+euler[g
];
}
ans=quickpowmod(a1,b1,g
);
cout<<f
[ans]<<endl;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: