ZOJ -- 2317(矩阵快速幂 + 大数简单处理)
2015-05-21 12:51
477 查看
题意:
给定三个参数 b(b<1e100),n(n<5),mod(mod<10000),行数为n列数为b 的0,1 矩阵中有多少个不含--- 边长为2且四个点颜色相同(全1或全0)的正方形。结果对mod取模。
思路:
从任意列状态出发,找到一个可以匹配的列状态,得到转移,那么如果一个状态成功转移b-1次,就是该问题的一个可行解。
由于n很小,列状态最多32个,可以先构造转移矩阵,A(n,n)。其中a(i,j)代表i状态可以与j匹配。显然该矩阵为对称矩阵。
那么A*A中每个元素代表的含义有是什么?
显然每个点 b(i,j) 是有a的第i行和第j列相乘得来的,第i行的每个元素可以定义为 :(经过0次转移,最终经由k转移至i有a(i,k)种方案)
那么A^(b-1)中每个元素a(i,j)的含义就是(经过b-1次转移,最终经由k转移至i有a(i,k)种方案)
该题目就是最终的矩阵元素求和。
给定三个参数 b(b<1e100),n(n<5),mod(mod<10000),行数为n列数为b 的0,1 矩阵中有多少个不含--- 边长为2且四个点颜色相同(全1或全0)的正方形。结果对mod取模。
思路:
从任意列状态出发,找到一个可以匹配的列状态,得到转移,那么如果一个状态成功转移b-1次,就是该问题的一个可行解。
由于n很小,列状态最多32个,可以先构造转移矩阵,A(n,n)。其中a(i,j)代表i状态可以与j匹配。显然该矩阵为对称矩阵。
那么A*A中每个元素代表的含义有是什么?
显然每个点 b(i,j) 是有a的第i行和第j列相乘得来的,第i行的每个元素可以定义为 :(经过0次转移,最终经由k转移至i有a(i,k)种方案)
那么A^(b-1)中每个元素a(i,j)的含义就是(经过b-1次转移,最终经由k转移至i有a(i,k)种方案)
该题目就是最终的矩阵元素求和。
#include <iostream> #include <stdio.h> #include <algorithm> #include <string.h> using namespace std; #define rep(i,n) for(int i=0;i<n;i++) int mod; const int maxn = 33; struct Matrix{ int m[maxn][maxn]; void init(){ for(int i=0;i<33;i++) for(int j=0;j<33;j++) m[i][j]=(i==j); } void show(int lim){ rep(i,lim){ rep(j,lim) cout<<m[i][j]<<" "; cout<<endl; } } }; string div2(string s){ string ans; int cnt=0; for(int i=0;i<s.length();i++){ char c=(s[i]-'0'+cnt*10)/2+'0'; cnt=(cnt*10+s[i]-'0')%2; if(!ans.empty()||c!='0') ans+=c; } if(ans.empty()) ans+='0'; return ans; } int mod2(string s){ int res=0; for(int i=0;i<s.size();i++) res=(res*10+s[i]-'0')%2; return res; } string sub1(string s){ int res=0; for(int i=s.size()-1;i>=0;i--){ if(s[i]=='0') s[i]='9'; else{ s[i]--; break; } } if(s[0]=='0') s=s.substr(1); return s; } int n; Matrix mult(Matrix A,Matrix B){ Matrix C; for(int i=0;i<(1<<n);i++) for(int j=0;j<(1<<n);j++){ C.m[i][j]=0; for(int k=0;k<(1<<n);k++) C.m[i][j]=(C.m[i][j]+A.m[i][k]*B.m[k][j])%mod; } return C; } Matrix Pow(Matrix A,string b){ Matrix res; res.init(); while(b!="0"){ if(mod2(b)) res=mult(res,A); A=mult(A,A); b=div2(b); } return res; } char b[110]; int main() { int T; scanf("%d",&T); while(T--){ scanf("%s %d %d",b,&n,&mod); string ss(b); ss=sub1(ss); Matrix A; for(int i=0;i<(1<<n);i++) for(int j=0;j<(1<<n);j++){ A.m[i][j]=1; for(int k=0;k<n-1;k++){ if(((i>>k)&1) && ((j>>k)&1) && ((i>>(k+1))&1) && ((j>>(k+1))&1)) A.m[i][j]=0; if(!((i>>k)&1) && !((j>>k)&1) && !((i>>(k+1))&1) && !((j>>(k+1))&1)) A.m[i][j]=0; } } Matrix res=Pow(A,ss); int sum=0; rep(i,(1<<n)) rep(j,(1<<n)) sum=(sum+res.m[i][j])%mod; cout<<sum<<endl; if(T) cout<<endl; } return 0; }
相关文章推荐
- zoj 2974 Just Pour the Water (矩阵快速幂,简单)
- ZOJ 2317 Nice Patterns Strike Back(矩阵快速幂)
- ZOJ 2853 Evolution 【简单矩阵快速幂】
- poj 3070 矩阵快速幂简单题
- zoj Fibonacci Numbers ( java , 简单 ,大数)
- 快速简单处理anr
- Anddroid 图片模糊处理——RenderScript :简单而快速的图像处理
- zoj 2714 Windows Message Queue(优先队列、简单的二叉堆处理)
- hdu 1575 Tr A(矩阵快速幂,简单)
- 矩阵快速幂ZOJ - 3497(矩阵在图的联通
- zoj 3497 Mistwald 矩阵快速幂
- Codeforces Round #420 (Div. 2) Okabe and El Psy Kongroo[矩阵快速幂+细节处理]
- ZOJ 2853 Evolution【矩阵快速幂】
- 矩阵快速幂 zoj-3690 Choosing number
- ZOJ 3497 Mistwald(矩阵快速幂)
- ZOJ 3690 Choosing number(矩阵快速幂)
- HUD - 1575 - Tr A ( 矩阵快速幂,简单题目 )
- zoj 2317 Nice Patterns Strike Back(矩阵乘法)
- 矩阵快速幂 ZOJ 2853 Evolution
- ZOJ 2974 Just Pour the Water(矩阵快速幂)