看题传送门:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1811
题目大意:
f(n) = a1 f(n- 1) + a2 f(n- 2) + a3 f(n-3) + ... + ad f(n- d), for n > d
你的任务是计算f(n)/m的余数
输入第一行为3个整数d,n,m
第二行为d个非负整数a1~d
第三行为d个非负整数f(1)~f(d)
嗯哼,我的数据结构的作业报告写了想提高的可以去切掉这题,星期四貌似要上去讲。总不能自己没A把,于是晚上A掉这题。不做死就不会死啊T T
傻B了一回,敲太快没结束条件,一直RE。然后以为是数组开太小又觉得不对啊。。。发现了之后习惯的写EOF。。。T T结束条件是3个0.。。笨蛋。。。。
言归正传,先简单的来。这也是我数据结构上次的作业
已知式子:F(n)=A*F(n-1)+B*F(n-2)(n>=2且 n 为整数)
输入第一行三个正整数 N,A 和 B(N<=10;1<=A、B<=100 且均为整数)。
接下来有 N 行,每行一个自然数 n(n<=100000000)。输出一行一个整数 F(n)结果对2013取模
输入
5 4 5
2
4
8
16
32
输出:
9
209
1377
182
9
输入:
2 100 100
10000000
100000000
输出:
1189
1585
以下直接复制我的结题报告:
(PS :PPT2013改成2003的格式这些公式都用图片保存。。。。。。T T.....可以复制文字了)
我们知道,计算机中用二进制来表示一个数。
如134的二进制为10000110
A^4能通过(A^2)*(A^2)得到,A^8又能通过(A^4)*(A^4)得到。
而A^134=(A^2)(A^4)(A^128)
可以根据这样的原理写出如下程序:
while(N>0) { if(N&1) res=res*A; n>>=1; A=A*A; }
>>表示右移运算。什么?你不知道什么是右移?
>>:低位溢出,符号位不变,并用符号位补溢出的高位。
什么意思?
比如刚才说的134的二进制为10000110,考虑符号位的话就是0 10000110。(正数)
右移一次后就变为001000011。
那么N& 1的意思是?
&运算代表逻辑与,是按位操作的。(很熟悉&&吧)
1的二进制前面都是0,最后一位是1,也就是说,当且仅当A最后一位是1时候,执行表达式。
我们知道,右移一次,该数/2。
故执行A*A
下面来看看A^134次方是怎么计算的。
为了方便叙述,符号位不写。。。。正数么。。都是0
10000110
执行if(N&1)判断为假,移位一次变为 1000011 此时A为原来的2次方
执行if(N&1)判断为真,执行一次res=A^2,移位100001 此时A为原来的4次方
执行if(N&1)判断为真,执行一次res=(A^2)(A^4),移位10000 此时A为原来的8次方
执行if(N&1)判断为假,移位一次变为 1000 此时A为原来的16次方
执行if(N&1)判断为假,移位一次变为 100 此时A为原来的32次方
执行if(N&1)判断为假,移位一次变为 10 此时A为原来的64次方
执行if(N&1)判断为假,移位一次变为 1 此时A为原来的128次方
执行if(N&1)判断为真,执行一次res==(A^2)(A^4)(A^128)移位一次变为0(前面符号位补最高位)此时A为原来的256次方
判断条件while(n>0) 不满足退出循环。
这就是整体的过程。希望能帮助到你。
好了 贴上这题的代码://重改了一下,优化可读性。 #include<cstdio> const int mod=2013; struct Matrix { int a[2][2]; Matrix & operator *(const Matrix &b) { Matrix c; c.a[0][0]=(a[0][0]*b.a[0][0] % mod + a[0][1]*b.a[1][0] % mod) %mod; c.a[0][1]=(a[0][0]*b.a[0][1] % mod + a[0][1]*b.a[1][1] % mod) %mod; c.a[1][0]=(a[1][0]*b.a[0][0] % mod + a[1][1]*b.a[1][0] % mod) %mod; c.a[1][1]=(a[1][0]*b.a[0][1] % mod + a[1][1]*b.a[1][1] % mod) %mod; *this=c; return *this; } }a; void myPow(int n) { Matrix b; //单位矩阵 b.a[0][0]=1; b.a[0][1]=0; b.a[1][0]=0; b.a[1][1]=1; while(n>0) { if(1&n) b=b*a; a=a*a; n>>=1; } a=b; } int main() { int N,A,B; scanf("%d%d%d",&N,&A,&B); while(N--) { int n; scanf("%d",&n); if(n==1||n==0) printf("1\n"); else { a.a[0][0]=A; a.a[0][1]=B; a.a[1][0]=1; a.a[1][1]=0; myPow(n-1); printf("%d\n",(a.a[0][0] + a.a[0][1]) % mod); } } }
OK这个10870题同理
图片之后补上。先去睡觉~~~~~~
上代码~嘻嘻
#include<cstdio> #include<cstring> const int MAXN=20; long long d,n,mod; long long f[MAXN]; struct Matrix { long long a[MAXN][MAXN]; void init() { memset(a,0,sizeof(a)); } Matrix() { memset(a,0,sizeof(a)); } Matrix &operator *(const Matrix &b) { Matrix temp; //memset(temp.a,0,sizeof(temp.a)); for(int i=0;i<d;i++) { for(int j=0;j<d;j++) { for(int k=0;k<d;k++) { temp.a[i][j]=(temp.a[i][j]+a[i][k]*b.a[k][j] ) %mod; } } } *this=temp; return *this; } }a; void myPow(long long n) { Matrix b; //单位矩阵 for(int i=0;i<d;i++) b.a[i][i]= 1; while(n>0) { if(1&n) b=b*a; a=a*a; n>>=1; } a=b; } int main() { while(scanf("%lld%lld%lld",&d,&n,&mod),d||n||mod) { a.init(); for(int i=0;i<d;i++) { scanf("%lld",&a.a[0][i]); a.a[0][i]%=mod; } for(int i=0;i<d;i++) { scanf("%lld",&f[i]); f[i]%=mod; } for(int i=1;i<d;i++) { a.a[i][i-1]=1; } myPow(n-d); long long ans=0; for(int i=0;i<d;i++) ans=(ans+a.a[0][i]*f[d-i-1]) %mod; printf("%lld\n",ans); } return 0; }