http://acm.hdu.edu.cn/webcontest/contest_show.php?cid=6930
1000:
题意:裸的斐波拉契,裸的不能再裸 n<10^12;
代码:
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #define oo 0x13131313 #define LL long long using namespace std; struct node { int mat[2][2]; }; node a={1,1,1,0}; node ret={1,0,0,1}; node NUL={0,0,0,0}; node matmult(node A,node B,int mod) { node C=NUL; for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) { C.mat[i][j]=(C.mat[i][j]+A.mat[i][k]*B.mat[k][j])%mod; } return C; } node quickmatpow(node A,LL n,int mod) { node c=ret; while(n!=0) { if(n&1==1) c=matmult(c,A,mod); n=n>>1; A=matmult(A,A,mod); } return c; } LL n; void init() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); } int main() { // init(); node c; while(cin>>n&&n!=-1) { c=quickmatpow(a,n,10000); printf("%d ",c.mat[0][1]); } }
1001
题意
A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973。
裸的 没什么好说的
/* 第一次没过样例是因为 写ret 的时候 只给对角线赋值为1 忘记clear了 */ #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #define oo 0x13131313 #define LL long long using namespace std; void init() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); } struct node { int mat[15][15]; void clear() { for(int i=0;i<15;i++) for(int j=0;j<15;j++) mat[i][j]=0; } void ret() { for(int i=0;i<15;i++) for(int j=0;j<15;j++) mat[i][j]=0; for(int i=0;i<15;i++) mat[i][i]=1; } }; node fir; LL n,k; node matmult(node a,node b,int mod) { node c; c.clear(); for(int i=0;i<n;i++) for(int j=0;j<n;j++) for(int k=0;k<n;k++) c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod; return c; } node quickmatpow(node a,LL n,int mod) { node c; c.ret(); while(n!=0) { if(n&1==1) c=matmult(c,a,mod); n=n>>1; a=matmult(a,a,mod); } return c; } void input() { scanf("%I64d%I64d",&n,&k); for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%d",&fir.mat[i][j]); } void solve() { node c; int ans=0; c=quickmatpow(fir,k,9973); for(int i=0;i<n;i++) { ans=(ans+c.mat[i][i])%9973; } printf("%d ",ans); } int main() { // init(); int T; cin>>T; while(T--) { input(); solve(); } return 0; }
1002
题意:
A是一个矩阵 计算S=A+A^2......A^k-1+A^k;
区分奇偶来二分! 看了题解才会做的
本来的想法是涉及到矩阵的逆的
/* 1.WA 不明原因 改成全long long 2. 2 1000000 4 0 1 1 1 99%错误答案: 0 0 0 0 调试原因:不清楚 3.WA 继续调试2 4.发现原因 n为奇数时处理错误 */ #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #define oo 0x13131313 #define LL long long using namespace std; struct node { LL mat[40][40]; void clear() { for(int i=0;i<40;i++) for(int j=0;j<40;j++) mat[i][j]=0; } void ret() { clear(); for(int i=0;i<40;i++) mat[i][i]=1; } }; LL n,k,m; node A; void init() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); } void input() { for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%I64d",&A.mat[i][j]); } node matmult(node a,node b,LL mod) { node c; c.clear(); for(int i=0;i<n;i++) for(int j=0;j<n;j++) for(int k=0;k<n;k++) c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod; return c; } node quickmatpow(node a,LL n,LL mod) { node c; c.ret(); while(n!=0) { if(n&1==1) c=matmult(c,a,mod); n=n>>1; a=matmult(a,a,mod); } return c; } node matadd(node a,node b,LL mod) { node c; for(int i=0;i<n;i++) for(int j=0;j<n;j++) c.mat[i][j]=(a.mat[i][j]+b.mat[i][j])%mod; return c; } node getans(int n,int mod) { node c,d; c.clear(); d.clear(); if(n==1) return A; else { c=getans(n/2,mod); if(n%2==0) { d=quickmatpow(A,n/2,mod); return matadd(c,matmult(d,c,mod),mod); } else { d=quickmatpow(A,(n/2)+1,mod); return matadd(d,matadd(c,matmult(d,c,mod),mod),mod); } } } void solve() { node ans; ans.clear(); ans=getans(k,m); for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { printf("%I64d",ans.mat[i][j]); if(j!=n-1) printf(" "); } printf(" "); } } int main() { //init(); while(cin>>n>>k>>m) { input(); solve(); } }
1003
题意:
询问长度为N的队伍中 可能为M,或F 问不存在 FFF或FMF的排列总数。
之前做过的一道题
http://blog.csdn.net/zy691357966/article/details/43084647
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #define oo 0x13131313 using namespace std; int L,M; struct node { int mat[5][5]; }a,e,ans; int mat2[5]; void CSH() { mat2[1]=9; mat2[2]=6; mat2[3]=4; mat2[4]=2; for(int i=1;i<=4;i++) { e.mat[i][i]=1; mat2[i]=mat2[i]%M; } memset(a.mat,0,sizeof(a.mat)); a.mat[1][1]=a.mat[1][3]=a.mat[1][4]=1; a.mat[2][1]=a.mat[3][2]=a.mat[4][3]=1; } node MatrixMult(node A,node B,int mod) { node p; memset(p.mat,0,sizeof(p.mat)); for(int i=1;i<=4;i++) for(int j=1;j<=4;j++) { for(int k=1;k<=4;k++) p.mat[i][j]+=A.mat[i][k]*B.mat[k][j]; p.mat[i][j]=p.mat[i][j]%mod; } return p; } node kuaisumi(node A,int N,int mod) { node di=e; while(N>0) { if(N&1) { di=MatrixMult(di,A,mod); } A=MatrixMult(A,A,mod); N=N>>1; } return di; } void solve() { int ANS=0; for(int i=1;i<=4;i++) { ANS+=ans.mat[1][i]*mat2[i]; ANS=ANS%M; } printf("%d ",ANS); } int main() { while(cin>>L>>M) { CSH(); if(L>4) ans=kuaisumi(a,L-4,M); if(L>4) solve(); else printf("%d ",mat2[L]); } return 0; }
1004
题目大意:
If x < 10 f(x) = x.
If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10);
And ai(0<=i<=9) can only be 0 or 1 .
齐次递推,很容易由1003 得出公式
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #define LL long long #define oo 0x13131313 using namespace std; LL k,m; void init() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); } struct node { LL mat[15][15]; void clear() {memset(mat,0,sizeof(mat));} void ret() { clear(); for(int i=0;i<15;i++) mat[i][i]=1; } }; node A; void input() { A.clear(); for(int i=0;i<10;i++) scanf("%d",&A.mat[0][i]); for(int i=1;i<10;i++) A.mat[i][i-1]=1; } node matmult(node a,node b,LL mod) { node c;c.clear(); for(int i=0;i<10;i++) for(int j=0;j<10;j++) for(int k=0;k<10;k++) c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod; return c; } node quickmatpow(node a,LL n,LL mod) { node c;c.ret(); while(n!=0) { if(n&1==1) c=matmult(c,a,mod); n=n>>1; a=matmult(a,a,mod); } return c; } void solve() { LL ans=0; node c;c.clear(); c=quickmatpow(A,k-9,m); for(int i=0;i<10;i++) ans=(ans+c.mat[0][i]*(9-i))%m; printf("%I64d ",ans); } int main() { // init(); while(cin>>k>>m) { input(); solve(); } return 0; }
接下来几个题目太强悍了 我必须新写一篇