您的位置:首页 > 其它

hdu 5451 Best Solver(2015沈阳赛区网赛)

2015-09-19 18:36 267 查看


Best Solver

Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)

Total Submission(s): 78 Accepted Submission(s): 26



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)

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.

Output

The output contains exactly T lines.

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


解题思路:

这道题跟斐波拉契数列有关,斐波拉契数列通项公式an=((1+√5)/2)^n+(1-√5)/2)^n,这题也可以转化为an=(5+2*sqrt(6))^n+(5-2*sqrt(6))^n的形式,则an一定是整数的形式,

因为an=((5+sqrt(6))+(5-sqrt(6))^n-2*(5+sqrt(6))*(5-sqrt(6)),(5+sqrt(6)+5-sqrt(6))^n=10^n,2*(5+sqrt(6))*(5-sqrt(6))=2,
所以an一定为整数,0<(5-2*sqrt(6)<1,所以0<(5-2*sqrt(6))^n<1,所以这题的y值是an-1。
就那现在问题就是,怎么来快速的求an?再参考菲波那契数列,通式怎么表达的。a
=a[n-1]+a[n-2]。那这里也
可以用类似的表达式,a
=p*a[n-1]+q*a[n-2]。带入几个数求得p=10,q=-1,于是通项公式为即a
=10*a[n-1]-*a[n-2]。

由于本题的x比较大,且m比较小,于是可以找循环节,由于是递推关系,后一个只与它前2个有关,于是循环节最大
为m方,另外,循环节肯定从序列开头开始(打表发现的)。

代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn=47337;
bool vis[maxn];
int prim[maxn];
int a[maxn];
int judge(int m)
{
a[0]=10%m;
a[1]=98%m;
for(int j=2;; j++)
{
a[j]=(a[j-1]*10-a[j-2]+m)%m;
//int sign=0;
if(a[j-1]==a[0]&&a[j]==a[1])
return j-1;
}
}
int pow_mod(int x,int mod)
{
long long ans=1,cur=2;
while(x)
{
if(x&1)
ans=(ans*cur)%mod;
cur=(cur*cur)%mod;
x=(x>>1);
}
return ans;
}
int main()
{
int t,ca=1;
scanf("%d",&t);
while(t--)
{
int m;
long long x;
scanf("%I64d%d",&x,&m);
int cmr=judge(m);
int cwt=pow_mod(x,cmr);
printf("Case #%d: ",ca++);
printf("%d\n",(a[cwt]-1+m)%m);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: