美丽家园
2015-08-07 21:39
211 查看
题意:
要你求在N * M的图中每个格子涂上黑色或白色的方案数对P取模后的结果,要满足每个2*2的区域里不能只有一种颜色。
N≤10100N\le 10^{100} ,M≤5M\le 5,P≤10000P\le 10000
分析:
看到N这么大,M这么小,很快想到快速幂。若从上往下做的话,每一行对它有影响的只有它的上一行,所以可以先搜索出转移矩阵,然后快速幂(注意高精度)。
要你求在N * M的图中每个格子涂上黑色或白色的方案数对P取模后的结果,要满足每个2*2的区域里不能只有一种颜色。
N≤10100N\le 10^{100} ,M≤5M\le 5,P≤10000P\le 10000
分析:
看到N这么大,M这么小,很快想到快速幂。若从上往下做的话,每一行对它有影响的只有它的上一行,所以可以先搜索出转移矩阵,然后快速幂(注意高精度)。
#include <cstdio> #include <cstring> using namespace std; const int M = 1 << 5,N = 110; struct jz { int s[M][M]; } s,re; struct gjd { int len,s ; } n; int m,P,len; bool p[2][M]; char in ; bool check(int x,int t) { if (x == 1) return true; if (p[0][x] != t || p[0][x - 1] != t || p[1][x - 1] != t) return true; return false; } void dfs(int st,int dep,int h,int last) { if (h == 0) { if (dep > m) { dfs(0,1,2,st); return; } p[0][dep] = true; dfs(st << 1 | 1,dep + 1,h,0); p[0][dep] = false; dfs(st << 1,dep + 1,h,0); } else { if (dep > m) { s.s[last][st] = 1; return; } if (check(dep,1)) { p[1][dep] = true; dfs(st << 1 | 1,dep + 1,h,last); p[1][dep] = false; } if (check(dep,0)) dfs(st << 1,dep + 1,h,last); } } jz calc(jz a,jz b) { jz c; memset(c.s,0,sizeof(c.s)); for (int k = 0;k <= len;k ++) { for (int i = 0;i <= len;i ++) { for (int j = 0;j <= len;j ++) { c.s[i][j] = (c.s[i][j] + a.s[i][k] * b.s[k][j] % P) % P; } } } return c; } void div() { for (int i = n.len;i;i --) { if (i > 1) n.s[i - 1] += (n.s[i] & 1) * 10; n.s[i] /= 2; } while (!n.s[n.len]) n.len --; } void fast() { if (n.len == 1 && n.s[1] == 1) return; int flag = 0; if (n.s[1] & 1) flag = 1; div(); fast(); re = calc(re,re); if (flag) re = calc(re,s); } void init() { scanf(" %s%d%d",&in,&m,&P); n.len = strlen(in); int i; for (i = 0;i < n.len;i ++) if (in[i] == ' ') break; for (int j = i - 1;j >= 0;j --) n.s[i - 1 - j + 1] = in[j] - '0'; } int main() { init(); if (n.len == 1 && n.s[1] == 1) printf("%d",(1 << m) % P); else { n.s[1] --; int i = 1; while (n.s[i] < 0) n.s[i] += 10,n.s[i + 1] --,i ++; while (!n.s[n.len]) n.len --; len = (1 << m) - 1; dfs(0,1,0,0); memcpy(re.s,s.s,sizeof(s.s)); fast(); int ans = 0; for (int i = 0;i <= len;i ++) { for (int j = 0;j <= len;j ++) ans = (ans + re.s[i][j]) % P; } printf("%d",ans); } }
相关文章推荐
- 基于GPU的粒子系统
- Dining (POJ No.3281) 网络流经典题
- hdu 1058 Humble Number
- Python字符串操作之字符大小写转换
- Qt_翻译小工具
- 学习zepto.js(Hello World)
- django的模型总结
- 抄书,分任务~~~~~~~
- Caffe学习:Forward and Backward
- iOS多线程与网络开发之大文件下载 (边下边写/暂停恢复下载/压缩解压zip/多线程下载)
- 简单多层神经网络实现异或XOR
- CS224d lecture 12札记
- Linux之文件操作(3)
- Java WEB: what's the difference between redirect and dispatch?
- UVa 227 Puzzle
- HDU 5294--Tricks Device【最小割 && 最短路处理,新建图】
- Windows Live Writer
- idea类似eclipse鼠标技巧java api信息
- 深度搜索DFS hdu-1312
- 【一些事晚报】大公司为什么爱“追杀”前高管