您的位置:首页 > 其它

hdu 5451(2015 ACM/ICPC Asia Regional Shenyang Online)

2015-10-04 09:50 281 查看
点击打开链接

题目的意思非常简单啦,就是一个式子对一个数取模,刚开始的时候有人说是费马小定理,现在想来完全不对,因为M这个数很小,有可能不满足费马小定理的条件。

还有就是,这个式子结果并不是整数需要取整(向下取整,以前有个类似的题是向上取整







嘛,做个题需要知道共轭因子,5+26





的共轭因子为5-26






举个例子:设y的整数部分为H

当x=0时,y=5+26





,然后加一个共轭因子,y=5+26





+5-26





,大家会发现这两数的整数部分恰好差1,5-26






本身就是一个小数,再自身乘以多次的话,显然会变得越来越小,y=(5+26





)^n+(5-26





)^n,大家看到这个式子,不知道会不会有所启发,在高中的时候,我们求斐波拉契数列的通项公式,就是利用特征方程来求的,an+1=an+an-1;抽象出方程x^2=x+1,求出两根,最后在利用待定系数法求得

斐波那契数列通项公式



大家可以查阅相关的资料,嘛,这原理本身很复杂啦。

回到题目上来,以5+26





和5-26





这两根,构造一个方程,窝觉得比较容易想到:x^2-10*x+1=0,然后在变一下,an+2=10*an+1-an,这样基本工作就完成了,

重点来了:线性递推数列对一个数取模,结果是有周期的哦,大家可以来斐波拉契数列来验证,萌蠢的帕斯喵是不会证明这个原理啦。还有就是要强调一下,关于找周期,

网上几乎所有的代码都是,用for循环来遍历一遍,然后第一次出现与首项和次项相同时,就表明找到了周期,在这里帕斯喵要提一个问题,就是万一第三个不同怎么办呢?

嘻嘻嘻。。。。

代码:

#include <iostream>
#include <stdio.h>
using namespace std;
int a[100000];//周期有多大,可以先打表估计一下
//求周期
int M,mod;
int time()
{
a[0]=10%M,a[1]=98%M;//数列的初值
a[2]=970%M;
for(int i=3;;i++)
{
a[i]=((10*a[i-1]-a[i-2])%M+M)%M;//有可能为负数哦
if(a[i-1]==a[0]&&a[i]==a[1])
{
return i-1;
}
}
}
int quickmod(int a,int b)//快速幂
{
long long ans=1;
while(b)
{
if(b&1)
{
ans=ans*a%mod;
b--;
}
b=b>>1;
a=a%mod*a%mod;
}
return ans;
}
int main()
{
int t,x,hehe,res,flag=0;
scanf("%d",&t);
while(t--)
{
flag++;
scanf("%d%d",&x,&M);
mod=time();
hehe=quickmod(2,x);//数列初始值从0开始的,所以不需要加一
res=(a[hehe]-1)%M;
printf("Case #%d: %d\n",flag,res);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: