51nod1668非010串+矩阵快速幂
来源:互联网 发布:淘宝代理怎么做 编辑:程序博客网 时间:2024/06/13 11:42
如果一个01字符串满足不存在010这样的子串,那么称它为非010串。
求长度为n的非010串的个数。(对1e9+7取模)
Input
一个数n,表示长度。(n<1e15)
Output
长度为n的非010串的个数。(对1e9+7取模)
Input示例
3
Output示例
7
解释:
000
001
011
100
101
110
111
对于这样的一个式子我们可以很快的写出dp的做法
#include<bits/stdc++.h>using namespace std;#define MOD 1000000007long long dp[100005][2];int main(){ int n; // while(scanf("%d",&n)!=EOF){ for(n=1;n<=500;n++){ memset(dp,0,sizeof(dp)); dp[1][0]=dp[1][1]=1; for(int i=2;i<=n;i++){ dp[i][0]+=dp[i-1][0]; dp[i][0]+=dp[i-1][1]-dp[i-2][0]+MOD; dp[i][1]+=dp[i-1][1]+dp[i-1][0]; dp[i][0]%=MOD; dp[i][1]%=MOD; } printf("%d\n",dp[n][0]+dp[n][1]); } return 0;}
然而这样的n有 1e15,不可能用这样的递推的dp去搞。
所以我们考虑那个dp的递推式子。
dp[i][0]+=dp[i-1][0];
dp[i][0]+=dp[i-1][1]-dp[i-2][0]
dp[i][1]+=dp[i-1][1]+dp[i-1][0]
。。。。。。。。。。。
dp[i][0]+=dp[i-1][0]+dp[i-1][1]-dp[i-2][0]
dp[i][1]+=dp[i-1][1]+dp[i-1][0]
维护dp[i][0],dp[i][1],dp[i-1][0],dp[i-1][1]的一个矩阵
dp[i][0],dp[i][1],dp[i-1][0],dp[i-1][1]=dp[i-1][0],dp[i-1][1],dp[i-2][0],dp[i-2][1]*
1 1 1 0
1 1 0 1
-1 0 0 0
0 0 0 0
所以,然后直接矩阵快速幂搞就好了。。
然后用dp的搞法验证下答案。好没问题,AC
2
4
7
12
21
37
65
114
200
351
616
1081
1897
3329
5842
10252
17991
31572
55405
#include<bits/stdc++.h>using namespace std;typedef long long LL;#define MOD 1000000007struct Mat{ int n,m; LL mat[9][9];};Mat operator *(Mat a,Mat b){ Mat c; memset(c.mat,0,sizeof(c.mat)); c.n = a.n,c.m = b.m; for(int i=1;i<=a.n;i++){ for(int j=1;j<=b.m;j++){ for(int k=1;k<=a.m;k++){ c.mat[i][j] += (a.mat[i][k]*b.mat[k][j])%MOD; c.mat[i][j] %= MOD; c.mat[i][j] = (c.mat[i][j]+ MOD)%MOD; } } } return c;}Mat operator +(Mat a,Mat b){ Mat c; memset(c.mat,0,sizeof(c.mat)); c.n = a.n,c.m = a.m; for(int i=1;i<=a.n;i++){ for(int j=1;j<=a.m;j++){ c.mat[i][j] = (a.mat[i][j]+b.mat[i][j])%MOD; } } return c;}Mat operator ^(Mat a,LL k){ Mat c; memset(c.mat,0,sizeof(c.mat)); c.n = a.n,c.m = a.n; for(int i=1;i<=a.n;i++)c.mat[i][i] = 1; while(k){ if(k&1){ c = c*a; } a = a*a; k>>=1; } return c;}void out(Mat a){ for(int i=1;i<=a.n;i++){ for(int j=1;j<=a.m;j++){ printf(j==a.m? "%I64d\n":"%I64d ",a.mat[i][j]); } }}LL quick_pow(LL a,LL b,LL p){ LL ret=1; a%=p; while(b){ if(b&1) ret=(ret*a)%p; a=(a*a)%p; b/=2; } return ret;}LL read(){ LL x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}int main(){ LL n; while(scanf("%I64d",&n)!=EOF){ if(n==1){ cout<<2<<endl; continue; } else if(n==2){ cout<<4<<endl; continue; } else if(n==3){ cout<<7<<endl; continue; } Mat a; a.n=a.m=4; a.mat[1][1]=1,a.mat[1][2]=1,a.mat[1][3]=1,a.mat[1][4]=0; a.mat[2][1]=1,a.mat[2][2]=1,a.mat[2][3]=0,a.mat[2][4]=1; a.mat[3][1]=-1,a.mat[3][2]=0,a.mat[3][3]=0,a.mat[3][4]=0; a.mat[4][1]=0,a.mat[4][2]=0,a.mat[4][3]=0,a.mat[4][4]=0; Mat a0; a0.n=1; a0.m=4; a0.mat[1][1]=2,a0.mat[1][2]=2,a0.mat[1][3]=1,a0.mat[1][4]=1; Mat ans=a0*(a^(n-2)); cout<<(ans.mat[1][1]+ans.mat[1][2])%MOD<<endl; } return 0;}
- 51nod1668非010串+矩阵快速幂
- 51nod1668 非010串(矩阵快速幂)
- [51nod1668]非010串
- 51nod 1668 非010串(矩阵快速幂)
- 51nod 非010串(dp找规律+矩阵快速幂)
- 矩阵快速幂 非详解
- 快速矩阵快速幂
- 51nod1126【矩阵快速幂】
- 51nod1126【矩阵快速幂】
- 51nod1242【矩阵快速幂】
- 51nod1113【矩阵快速幂】
- 矩阵快速幂 51nod
- 51 Nod1113 矩阵快速幂
- 转移矩阵+矩阵快速幂
- 矩阵乘法 矩阵快速幂
- 构造矩阵+矩阵快速幂
- 矩阵快速幂,矩阵加法,矩阵乘法
- 快速幂||矩阵快速幂
- ZipEntry实现文件解压缩与目录解压缩
- Unity3D游戏中隐藏鼠标光标
- Oracle 12cR1新特性导致的性能问题---MMON进程消耗了很高的CPU使用率.
- 面试题学习笔记--java基础篇
- java移位运算符:<<(左移)、>>(带符号右移)和>>>(无符号右移)
- 51nod1668非010串+矩阵快速幂
- 【转发】 ionic更新app
- MT7628实现Amazon alexa语音控制
- 自定义Adapter的接口,方便回调。Adapter与Activity之间的回调
- 解决linux重启apache遇到:Could not reliably determine the server's ...的错误
- 2016/9/28leetcode笔记,
- Intellij idea 与 MyEclipse
- 友盟多渠道打包总结
- C#模拟鼠标操作