zoj3707(Calculate Prime S)解题报告
1.计算(a/b)%c,其中b能整除a
设a=b*r=(bc)*s+b*t
则(b*t)为a除以bc的余数
r=c*s+t
而
(a/b)%c=r%c=t
(a%bc)/b=(b*t)/b=t
所以对于b与c互素和不互素都有(a/b)%c=(a%bc)/b成立。
当bc不大时,先取模bc,再除b
如果b与c互素,则(a/b)%c=a*b^(phi(c)-1)%c
待证
2.与集合子集
斐波那契数列的第n+2项同时也代表了集合{1,2,...,n}中所有不包含相邻正整数的子集个数。
证明:归纳法证明——
n=1时,相应子集个数为2,为f(3);
n=2时,相应子集个数为3,为f(4);
n>=3时,若集合{1,2,...,n-2}的相应子集为f(n),集合{1,2,...,n-1}的相应子集为f(n-1)
则对于集合{1,2,...,n}:
包含n的子集(即不包含n-1,在最大项可以为n-2的子集基础上加上数字n)个数为f(n)
不包含n的子集个数为f(n+1)(最大项可以为n-1的子集)
所以集合{1,2,...,n}的相应子集为f(n)+f(n+1)=f(n+2)
所以得证
3.gcd(fib(n),fib(m))=fib(gcd(n,m))
证明:http://www.cnblogs.com/cmyg/p/6618893.html
当一个数n与其它数m的最大公约数为为1或2时,则fib(n)和fib(m)的最大公约数为fib(1)或fib(2),为1。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <stdbool.h> 4 #include <malloc.h> 5 #include <memory.h> 6 7 #define ansnum 20000000 8 #define anszhi 2000000 9 10 struct node 11 { 12 long long mat[2][2]; 13 }; 14 long *zhi; 15 bool *vis; 16 long yu; 17 18 void Prime() 19 { 20 long i,j,ans=0; 21 memset(vis,true,sizeof(bool)*ansnum); 22 for (i=2;i<ansnum;i++) 23 { 24 if (vis[i]) 25 { 26 ans++; 27 zhi[ans]=i; 28 } 29 for (j=1;j<=ans;j++) 30 { 31 if (i*zhi[j]>=ansnum) 32 break; 33 vis[i*zhi[j]]=false; 34 if (i%zhi[j]==0) 35 break; 36 } 37 } 38 zhi[1]=3; 39 zhi[2]=4; 40 } 41 42 struct node count_mat(struct node a,struct node b) 43 { 44 long i,j; 45 struct node c; 46 for (i=0;i<2;i++) 47 for (j=0;j<2;j++) 48 c.mat[i][j]=(a.mat[i][0]*b.mat[0][j] 49 +a.mat[i][1]*b.mat[1][j])%yu; 50 return c; 51 } 52 53 long fib(long t) 54 { 55 struct node m,r; 56 m.mat[0][0]=0; 57 m.mat[0][1]=1; 58 m.mat[1][0]=1; 59 m.mat[1][1]=1; 60 61 r.mat[0][0]=1; 62 r.mat[0][1]=0; 63 r.mat[1][0]=0; 64 r.mat[1][1]=1; 65 t--; 66 while (t) 67 { 68 if ((t & 1)==1) 69 r=count_mat(r,m); 70 t>>=1; 71 m=count_mat(m,m); 72 } 73 return (r.mat[0][0]+r.mat[0][1])%yu; 74 } 75 76 int main() 77 { 78 vis=(bool *) malloc (sizeof(bool)*ansnum); 79 zhi=(long *) malloc (sizeof(long)*anszhi); 80 long n,k,x,m,i,j; 81 Prime(); 82 scanf("%ld",&n); 83 for (i=1;i<=n;i++) 84 { 85 scanf("%ld%ld%ld",&k,&x,&m); 86 yu=x; 87 for (j=zhi[k];;j++) 88 if (fib(j)==0) 89 break; 90 yu=x*m; 91 printf("%ld\n",fib(j)/x); 92 } 93 return 0; 94 } 95 /* 96 5 97 5 13 10 98 1 11 3 99 5 2 5 100 5 5 6 101 1000000 100 1000000 102 */