ZOJ 2317 高精度+状压DP+矩阵快速幂
来源:互联网 发布:sql酒店管理系统 编辑:程序博客网 时间:2024/06/05 08:40
题意:给你一个NxM的格子,每个格子可以涂黑色或者白色,但是不允许任意2x2的格子同色,最多有多少方案。
分析:注意要判断一个pattern是不是nice的,只要检查相邻的两行的状态。由于m很小,可以将行的状态用2^m的掩码来表示,dp[k][i]表示k行,最后一行状态为i的pattern个数,如果状态i和状态j不冲突,那么dp[k+1][j]+=dp[k][i]。由于问题中n很大,这样一行一行转移的动态规划肯定是吃不消的。注意每次的转移其实都是一样的,记dp[k]为一个列向量,建立一个2m*2m的01矩阵A,矩阵元素对应表示两行状态是否冲突,则dp[k+1]=A*dp[k],dp[n]=A^n*dp[0],而A^n可以利用经典的快速乘法运算来计算。
代码:
#pragma comment(linker,"/STACK:102400000,102400000")#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#include <vector>#include <string>#include <math.h>#include <queue>#include <stack>#include <map>#include <set>using namespace std;typedef long long ll;const int INF=1000000000;const int maxlength=9999;class bigint{public:int oper, length, a[maxlength];bigint(int = 0);~bigint();void check();void operator = (bigint m);void operator = (int m);void operator = (char *s);bool operator < (bigint m);bool operator <= (bigint m);bool operator > (bigint m);bool operator >= (bigint m);bool operator == (bigint m);bool operator != (bigint m);bigint operator - ();bigint operator + (bigint m);void operator += (bigint m);bigint operator - (bigint m);void operator -= (bigint m);bigint operator * (bigint m);bigint operator * (int m);void operator *= (bigint m);void operator *= (int m);bigint operator / (bigint m);bigint operator / (int m);void operator /= (bigint m);void operator /= (int m);bigint operator % (bigint m);bigint operator % (int m);void operator %= (bigint m);void operator %= (int m);};bigint::bigint(int v){(*this) = v;this -> check();}bigint::~bigint(){}void bigint::check(){for(; length > 0 && a[length] == 0; length--);if(length == 0)oper = 1;}void bigint::operator = (bigint m){oper = m.oper;length = m.length;memcpy(a, m.a, maxlength * sizeof(int));this -> check();}void bigint::operator = (int m){oper = (m > 0)? 1: -1;m = abs(m);memset(a, 0, maxlength*sizeof(int));for(length = 0; m > 0; m = m / 10000)a[++length] = m % 10000;this -> check();}void bigint::operator = (char *s){int i, L;(*this) = 0;if(s[0] == '-' || s[0] == '+'){if(s[0] == '-')oper = -1;L = strlen(s);for(i = 0; i < L; i++)s[i] = s[i+1];}L = strlen(s);length = (L + 3) / 4;for(i = 0; i < L; i++)a[(L - i + 3) / 4] = a[(L - i + 3) / 4] * 10 + (s[i] - 48);this -> check();}bool bigint::operator < (bigint m){if(oper != m.oper)return oper < m.oper;if(length != m.length)return oper * length < m.length * oper;for(int i = length; i >= 1; i--)if(a[i]!=m.a[i])return a[i]*oper<m.a[i]*oper;return false;}bool bigint::operator <= (bigint m){return !(m < (*this));}bool bigint::operator>(bigint m){return m < (*this);}bool bigint::operator >= (bigint m){return !((*this) < m);}bool bigint::operator == (bigint m){return (!((*this) < m)) && (!(m < (*this)));}bool bigint::operator != (bigint m){return ((*this) < m) || (m < (*this));}bigint bigint::operator - (){bigint c = (*this);c.oper = -c.oper;c.check();return c;}bigint abs(bigint m){bigint c = m;c.oper = abs(c.oper);c.check();return c;}bigint bigint::operator + (bigint m){if(m.length == 0)return (*this);if(length == 0)return m;if(oper == m.oper){bigint c;c.oper = oper;c.length = max(length, m.length) + 1;for(int i = 1, temp = 0; i <= c.length; i++)c.a[i] = (temp = (temp / 10000 + a[i] + m.a[i])) % 10000;c.check();return c;}return (*this) - (-m);}bigint bigint::operator - (bigint m){if(m.length == 0)return (*this);if(length == 0)return (-m);if(oper == m.oper){bigint c;if(abs(*this) >= abs(m)){c.oper = oper;c.length = length;for (int i = 1, temp = 0; i <= length; i++)c.a[i] = ((temp = (-int(temp < 0) + a[i] - m.a[i])) + 10000) % 10000;c.check();return c;}return -(m - (*this));}return (*this) + (-m);}bigint bigint::operator * (bigint m){bigint c;c.oper = oper * m.oper;c.length = length + m.length;for(int i = 1; i <= m.length; i++){int number = m.a[i],j,temp = 0;for (j = 1; j <= length; j++)c.a[i + j - 1] += number * a[j];if (i % 10 == 0 || i == m.length)for (j = 1; j <= c.length; j++)c.a[j] = (temp = (temp / 10000) + c.a[j]) % 10000;}c.check();return c;}bigint bigint::operator * (int m){if(m < 0)return -((*this) * (-m));if(m > 100000)return (*this) * bigint(m);bigint c;c.length = length + 2;c.oper = oper;int t = 0;for(int i = 1; i <= c.length; i++)c.a[i] = (t = (t / 10000 + a[i] * m)) % 10000;c.check();return c;}bigint bigint::operator / (bigint m){if(m.length == 0){printf("Division by zero.\n");exit(0);}if(abs(*this) < abs(m))return 0;bigint c, left;c.oper = oper / m.oper;m.oper = 1;c.length = length - m.length + 1;left.length = m.length - 1;memcpy(left.a + 1, a + length - left.length + 1, left.length * sizeof(int));for(int i = c.length; i >= 1; i--){left = left * 10000 + a[i];int head = 0, tail = 10000, mid;while(head + 1 < tail){mid = (head + tail) >> 1;if(m * mid <= left)head = mid;elsetail = mid;}c.a[i] = head;left -= m * head;}c.check();return c;}bigint bigint::operator / (int m){if(m < 0)return -((*this) / (-m));if(m > 100000)return (*this) / bigint(m);bigint c;c.oper = oper;c.length = length;int t = 0;for(int i = c.length; i >= 1; i--)c.a[i] = (t = (t % m * 10000 + a[i])) / m;c.check();return c;}bigint bigint::operator % (bigint m){return (*this) - ((*this) / m) * m;}bigint bigint::operator % (int m){if (m < 0)return -((*this) % (-m));if (m > 100000)return (*this) % bigint(m);int t = 0;for(int i = length; i >= 1; i--)t = (t * 10000 + a[i]) % m;return t;}void bigint::operator += (bigint m){(*this) = (*this) + m;}void bigint::operator -= (bigint m){(*this) = (*this) - m;}void bigint::operator *= (bigint m){(*this) = (*this) * m;}void bigint::operator /= (bigint m){(*this) = (*this) / m;}void bigint::operator %= (bigint m){(*this) = (*this) % m;}void bigint::operator *= (int m){(*this) = (*this) * m;}void bigint::operator /= (int m){(*this) = (*this) / m;}void bigint::operator %= (int m){(*this) = (*this) % m;}int mod;const int maxn=40;struct p{ int m[maxn][maxn]; int h,l; p() { memset(m,0,sizeof(m)); }};p multi(p a,p b){ int i,j,k; p c; for(i=1;i<=a.h;i++) { for(j=1;j<=b.l;j++) { c.m[i][j]=0; for(k=1;k<=a.h;k++) c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%mod; } } c.h=a.h; c.l=b.l; return c;}p quickpow(p a,bigint n){ int i; p s; s.h=s.l=a.h; for(i=1;i<=a.h;i++) s.m[i][i]=1; while(n!=0) { if(n%2!=0) s=multi(s,a); a=multi(a,a); n=n/2; } return s;}void qs(int* a,int ws,int shu){ int ans=0,i; for(int i=1;i<=ws;i++)a[i]=0; while(shu) { a[++ans]=shu%2; shu=shu/2; } for(i=1;i<=ws/2;i++)swap(a[i],a[ws-i+1]); //for(i=1;i<=ws;i++)printf("%d",a[i]); //printf("\n");}int pd(int* a,int* b,int ws){ for(int i=1;i<ws;i++)if(a[i]==a[i+1]&&b[i]==b[i+1]&&a[i]==b[i])return 0; return 1;}int main(){ int t,m,i,j,mp[35][35],a[7],b[7],ret,cs=0;char s[10000];bigint B;scanf("%d",&t);while(t--){ if(cs>0)printf("\n"); cs++; scanf("%s%d%d",s,&m,&mod); B=s; for(i=0;i<(1<<m);i++){ qs(a,m,i); for(j=i;j<(1<<m);j++){ qs(b,m,j); if(pd(a,b,m))mp[i+1][j+1]=1; else mp[i+1][j+1]=0; } } for(i=1;i<=(1<<m);i++) for(j=1;j<=i;j++)mp[i][j]=mp[j][i]; //for(i=1;i<=(1<<m);i++){ //for(j=1;j<=(1<<m);j++)printf("%d",mp[i][j]); //printf("\n"); // } p c; for(i=1;i<=(1<<m);i++) for(j=1;j<=(1<<m);j++)c.m[i][j]=mp[i][j]; c.h=c.l=(1<<m); c=quickpow(c,B-1); ret=0; for(i=1;i<=(1<<m);i++){ for(j=1;j<=(1<<m);j++)ret+=c.m[i][j]; } printf("%d\n",ret%mod);}return 0;}
0 0
- ZOJ 2317 高精度+状压DP+矩阵快速幂
- zoj 3690 DP+矩阵快速幂
- 矩阵快速幂ZOJ
- Evolution +zoj+矩阵快速幂
- zoj 3497 矩阵快速幂
- zoj 3960(矩阵快速幂)
- 【NOI2012T1】随机数生成器-矩阵快速幂+高精度
- 【状压dp && 矩阵快速幂】 POJ
- ZOJ 3256 Tour in the Castle(插头DP+矩阵快速幂)
- ZOJ 2317Nice Patterns Strike Back(矩阵快速幂)
- ZOJ -- 2317(矩阵快速幂 + 大数简单处理)
- POJ3734Blocks DP&&矩阵快速幂
- 矩阵快速幂 zoj-3690 Choosing number
- ZOJ 3690 矩阵快速幂乘
- 【矩阵快速幂】ZOJ 2853 Evolution
- zoj 2853 Evolution(矩阵快速幂)
- ZOJ 2853 Evolution[ 矩阵快速幂 ]
- ZOJ 3497 Mistwald(矩阵快速幂)
- Android GridView属性集合
- poj3666
- wikioi 3116 高精度练习之加法
- poj3662
- 威尔逊定理
- ZOJ 2317 高精度+状压DP+矩阵快速幂
- poj3662 dij
- Web_FileUpload学习
- java模拟登录校内成绩查询网站,将获得的HTML代码用jsoup解析
- 背包问题(动态规划)
- hdu 1814 Peaceful Commission (2-sat 输出字典序最小路径)
- 【Java常用类库】_StringBuffer
- poj3614
- 【Java常用类库】_Runtime类