Best Solver
Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)Total Submission(s): 401 Accepted Submission(s): 212
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
本题正解是:快速矩阵乘法+ Fibonacci数列的循环节
以下是队里某同学的方法:
首先(5+2sqrt(6))^n + (5-2sqrt(6))^n 是一个整数,且(5-2sqrt(6))^n < 1
所以 (5+2sqrt(6))^n + (5-2sqrt(6))^n = x + y sqrt(6) + x - ysqrt(6)
所以算出 (5+2sqrt(6))^n的整数部分x,答案就是2*x-1
中间过程可以用取模操作。
他的思路是:1+2^x ,把1提出来,最后乘上即可。
对于{(5+2sqrt(6))^(2^n)}^2 = (5+2sqrt(6))^(2^(n+1))
这个乘法是有循环结的。
可能循环节开始位置不是(5+2sqrt(6))所以,预处理即可。
找到循环节以后,取模,然后快速矩阵乘即可。看代码。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cstdio>
using namespace std;
#define ll unsigned int
struct Node{
int a,b,t;
Node(){}
Node(int _a,int _t){
a = _a;
t = _t;
}
};
vector<Node> head[50000];
ll mod ;
struct Mat{
ll a[2][2];
Mat(){
memset(a,0,sizeof(a));
}
Mat operator *(const Mat & b){
Mat c;
memset(c.a,0,sizeof(c.a));
for(int i = 0;i < 2; i++)
for(int j = 0;j < 2; j++)
for(int k = 0;k < 2; k++)
c.a[i][j] = (c.a[i][j]+a[i][k]*b.a[k][j])%mod;
return c;
}
};
int main(){
ll t,n,m,tt=1;
scanf("%lld",&t);
while(t--){
scanf("%lld%lld",&n,&m);
mod = m;
for(int i = 0;i < m; i++)
head[i].clear();
Node a,b;
Mat x,y;
ll cnt = 1,be=0;
x.a[0][0] = x.a[1][1] = 5%mod;
x.a[0][1] = 12%mod;
x.a[1][0] = 2%mod;
y = x;
for(;;cnt++){
a.a = x.a[1][0];
a.b = x.a[0][0];
a.t = cnt;
int flag = 1;
for(int i = 0;i < head[a.b].size(); i++){
if(head[a.b][i].a == a.a){
flag = 0;
be = head[a.b][i].t;
}
}
if(flag==0) break;
head[a.b].push_back(a);
x = x*x;
}
cnt = cnt - be;
ll num = 0,ans;
x = y;
for(int i = 0;i < min(be,n); i++){
x = x*x;
}
if(n > be){
n -= be;
cnt = n%cnt;
for(int i = 0;i < cnt; i++)
x = x*x;
}
x = y * x;
ans = 2*x.a[0][0]-1;
ans %= mod;
printf("Case #%lld: %lld\n",tt++,ans);
}
return 0;
}
出题人的解法:(过后更新)