Hdu 5451 Best Solver(快速幂取模+循环节) -2015 ACM-ICPC沈阳网赛1002
Best Solver
Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)Total Submission(s): 736 Accepted Submission(s): 413
Problem Description
The so-called best problem solver can easily solve this problem, with his/her childhood sweetheart.
It is known that y=(5+26√)1+2x .
For a given integer x (0≤x<232) and a given prime number M (M≤46337) , print [y]%M . ( [y] means the integer part of y )
It is known that y=(5+26√)1+2x .
For a given integer x (0≤x<232) and a given prime number M (M≤46337) , print [y]%M . ( [y] means the integer part of y )
Input
An integer
T (1<T≤1000)
, indicating there are
T
test cases.
Following are T lines, each containing two integers x and M , as introduced above.
Following are T lines, each containing two integers x and M , as introduced above.
Output
The output contains exactly
T
lines.
Each line contains an integer representing [y]%M .
Each line contains an integer representing [y]%M .
Sample Input
7 0 46337 1 46337 3 46337 1 46337 21 46337 321 46337 4321 46337
Sample Output
Case #1: 97 Case #2: 969 Case #3: 16537 Case #4: 969 Case #5: 40453 Case #6: 10211 Case #7: 17947
Source
题意:对
y=(5+26√)1+2x
.这个式子x (0<=x<2^32)和一个素数M(M<=46337),求y的整数部分对M取余的结果
分析:由斐波那契数列通项公式联想到An=(5+2√6)^n+(5-2√6)^n
,明显对任何的n,an是整数,0<(5-2√
6)^n<1,所以(5+2√6)^n-(1-(5-2√6))
即是我们要求的(5+2√6)^n的整数部分,即是An -1。问题的关键变成了求An。
还是有由斐波那契数列通项公式的启发,设f[n]=p*f[n-1]+q*f[n-2],代入f[1],f[2],f[3]的值,可以得到p=10,
q=-1。于是我们有:
f[n]=10*f[n-1]-f[n-2]
给定x,由于x的值巨大,写程序打表,发现f[n]%M出现了循环节,所以1+2^x对循环节长度len取模后,可以求得结果。
AC代码:
#include<iostream>
#include<cstdio>
#include<sstream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#define INF 1<<29
#define eps 1e-9
#define LD long double
#define LL long long
const int maxn = 100000 + 10;
using namespace std;
int f[maxn];
int calc(int m)
{
f[1] = 10 % m;
f[2] = 98 % m;
for (int i = 3;; i++)
{
f[i] = (10 * f[i - 1]%m - f[i - 2]%m+m) % m;
if (f[i - 1] == 10 % m&&f[i] == 98 % m)
{
return i-2;
}
}
}
int pow_mod(int a, LL n, int m)
{
if (n == 0) return 1;
int x = pow_mod(a, n / 2, m);
long long ans = (long long)x*x%m;
if (n % 2 == 1) ans = ans*a%m;
return (int)ans;
}
int main()
{
#ifdef LOCAL
freopen("data.txt", "r", stdin);
#endif
int T;
cin >> T;
for (int i = 1; i <= T;++i)
{
cout << "Case #" << i << ": ";
int x, M;
cin >> x >> M;
memset(f, 0, sizeof(0));
int len=calc(M);
int find = (1 + pow_mod(2, x, len))%len;
cout << (f[find]-1+M)%M<<endl;
}
return 0;
}