题目链接:https://vjudge.net/problem/UVA-11582
题意:
输入两个非负整数a、b和正整数n(0<=a,b<2^64,1<=n<=1000),你的任务是计算f(ab)除以n的余数,f(0) = 0, f(1) = 1,且对于所有非负整数i,f(i + 2) = f(i + 1) + f(i)。
题解:
1、首先应注意到取值范围:a, b < 2^64 ,所以应用无符号整型
unsigned long long 取值范围:unsigned long long [int] 64 0 ~ 2^64-1 %I64u 、 %I64o 、 %I64x
long long 取值范围:[signed] long long [int] 64 -2^63 ~ 2^63-1 %I64d
而且输入不可以用scanf("%lld %lld %d", &a, &b, &n); 还是用cin。
2、斐波那契数列对n取模是有规律的,对n取模,最多n项,不会超过n^2项就会出现重复。求出循环周期(len)。
3、利用快速幂取模(对len取模),这样求出arr[ a^b % len ],就是答案。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<sstream>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<cmath>
#define up(i, x, y) for(int i = x; i <= y; i++)
#define down(i, x, y) for(int i = x; i >= y; i--)
#define MAXN ((int)1e6 + 10)
#define INF 0x3f3f3f3f
using namespace std;
typedef unsigned long long ull;
int arr[MAXN];
int pow_mod(ull a, ull n, int m) //快速幂取模
{
ull base = a, ans = 1;
while(n)
{
if(n & 1){
ans = ans * base % m;
}
base = base * base % m;
n >>= 1;
}
return (int)(ans % m);
}
int solve(ull a, ull b, int n)
{
int len = 1;
for(int i = 2; 1 ; i++)
{
arr[i] = (arr[i - 1] + arr[i - 2]) % n;
if(arr[i - 1] == arr[0] && arr[i] == arr[1]) {
len = i - 1; //周期
break;
}
}
int loc = pow_mod(a % len, b , len); //位置
return arr[loc];
}
int main()
{
int T; cin>>T;
while(T--){
ull a, b;
int n;
cin>>a>>b>>n;
arr[0] = 0, arr[1] = 1 % n;
cout<<solve(a, b, n)<<'\n';
}
return 0;
}