bzoj4417: [Shoi2013]超级跳马
来源:互联网 发布:java file.getname 编辑:程序博客网 时间:2024/06/04 17:40
题意
自己看
题解
你就随便矩阵快速幂一下就可以了
首先这题不难想到一个nm的做法,就是保存奇数列和偶数列的答案
看看代码就懂了吧
#include<cstdio>#include<cstring>const int N=55;int f[N][2];//哪一行 0:奇数列 1:偶数列 int n,m;int main(){ scanf("%d%d",&n,&m); memset(f,0,sizeof(f)); f[1][0]=1;int now=0; for (int u=2;u<m;u++) { for (int i=1;i<=n;i++) { f[i][now^1]+=f[i-1][now]+f[i][now]+f[i+1][now]; } now^=1; } printf("%d\n",f[n][now]+f[n-1][now]); return 0;}
然后你就可以尝试构造一个矩阵,让他快速幂一下
方法有很多
着这里是吧相邻的两列放在一起快速幂
矩阵大小1*(2n)
1~n是奇数位的和 n+1~2*n是偶数位的和
然后大力推他由上一个状态怎么推过来。。
for (LL u=1;u<=n;u++)//先把前面的搞好 { b.f[u][u]=1; b.f[u+n][u]=1; if (u>1) b.f[u+n][u-1]=1; if (u<n) b.f[u+n][u+1]=1; } for (LL u=n+1;u<=2*n;u++) { b.f[u][u]++; /*对应自己*/ b.f[u-n][u]++; if (u+1<=2*n) b.f[u+1][u]++; b.f[u][u]++; if (u-1>n) b.f[u-1][u]++; /*对应+1*/ if (u<2*n) { b.f[u-n+1][u]++; b.f[u][u]++; if (u+1<=2*n) b.f[u+1][u]++; if (u+2<=2*n) b.f[u+2][u]++; } /*对应-1*/ if (u>n+1) { b.f[u][u]++; b.f[u-n-1][u]++; if (u-1>n) b.f[u-1][u]++; if (u-2>n) b.f[u-2][u]++; } }
小于n位的情况是比较直观的
但是大于n的位就要要论一下了,因为他需要转移的状态在上一个矩阵没有直观地出现。。于是要手完一下
然后就快速幂一下就好了。
要注意n=1的情况,否则会WA(但是对拍时抄了一个人的代码,他的没判,对拍挂了,交上去A了,我也不知道为什么)
#include<cstdio>#include<cstdlib>#include<algorithm>#include<iostream>#include<cstring>using namespace std;typedef long long LL;const LL N=55;const LL MOD=30011;struct qt{ LL x,y;//大小 LL f[N*2][N*2]; friend qt operator * (qt a,qt b) { qt c;c.x=a.x;c.y=a.y; memset(c.f,0,sizeof(c.f)); for (LL u=1;u<=a.x;u++)//行 for (LL i=1;i<=a.y;i++)//列 for (LL j=1;j<=a.y;j++) c.f[u][i]=(c.f[u][i]+(a.f[u][j]*b.f[j][i])%MOD)%MOD; return c; }};//矩阵 qt a;//初始矩阵 qt b;//拿来乘的矩阵 LL n,m; void prepare ()//构造初始矩阵 { a.x=1;a.y=2*n;a.f[1][1]=1;a.f[1][n+1]=1;a.f[1][n+2]=1; b.x=2*n;b.y=2*n; for (LL u=1;u<=n;u++)//先把前面的搞好 { b.f[u][u]=1; b.f[u+n][u]=1; if (u>1) b.f[u+n][u-1]=1; if (u<n) b.f[u+n][u+1]=1; } for (LL u=n+1;u<=2*n;u++) { b.f[u][u]++; /*对应自己*/ b.f[u-n][u]++; if (u+1<=2*n) b.f[u+1][u]++; b.f[u][u]++; if (u-1>n) b.f[u-1][u]++; /*对应+1*/ if (u<2*n) { b.f[u-n+1][u]++; b.f[u][u]++; if (u+1<=2*n) b.f[u+1][u]++; if (u+2<=2*n) b.f[u+2][u]++; } /*对应-1*/ if (u>n+1) { b.f[u][u]++; b.f[u-n-1][u]++; if (u-1>n) b.f[u-1][u]++; if (u-2>n) b.f[u-2][u]++; } }}qt shen (qt x,LL y){ /*printf("%d\n",y); if (y==1) return x; printf("YES\n"); qt lalal=shen(x,y/2); lalal=lalal*lalal; printf("NO"); if (y%2!=0) lalal=lalal*x; return lalal;*/ qt ans;ans.x=x.x;ans.y=x.y; for(int i=1;i<=ans.x;i++) ans.f[i][i]=1; while(y) { if(y&1) ans=ans*x; x=x*x;y>>=1; } return ans;}void solve (){ LL t=(m-2)/2; a=a*shen(b,t); if (m%2!=0) { if (n!=1) printf("%lld\n",(a.f[1][n+n]+a.f[1][n+n-1])%MOD); else printf("%lld\n",a.f[1][2*n]); } else { if (n!=1) printf("%lld\n",(a.f[1][n]+a.f[1][n-1])%MOD); else printf("%lld\n",a.f[1][n]); }}int main(){ scanf("%lld%lld",&n,&m); prepare(); solve(); return 0;}
阅读全文
0 0
- [bzoj4417][SHOI2013]超级跳马
- BZOJ4417 [Shoi2013]超级跳马
- bzoj4417: [Shoi2013]超级跳马
- bzoj4417 超级跳马 矩阵乘法
- bzoj 4417: [Shoi2013]超级跳马
- bzoj 4417: [Shoi2013]超级跳马
- 矩阵乘 [Shoi2013]超级跳马
- 4417: [Shoi2013]超级跳马|DP+矩阵快速幂
- BZOJ 4417: [Shoi2013]超级跳马【矩阵快速幂优化dp
- bzoj 4417: [Shoi2013]超级跳马(矩阵合并+快速幂)
- 跳马
- 跳马
- 跳马
- 跳马
- 跳马
- 跳马问题
- 跳马问题
- 跳马问题
- 《深入浅出node.js》——setImmediate()与process.nextTick()
- 循环队列的表示与实现
- surfaceview组件的初始化
- js:innerHTML与innerText||textContent
- Flex布局和Grid布局
- bzoj4417: [Shoi2013]超级跳马
- ngrok-本地内网端口映射到外网
- 【vim】默认显示行号
- Outlook 2016 pst/ost邮件数据文件迁移实现
- 51Nod-1499-图
- jdk代理
- oracle调用netca、netmgr出现的空指针异常
- python爬虫模块小结
- 计算机网络学习相关的一些网站