Codeforces Round #420 E
Posted %%%%%
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #420 E相关的知识,希望对你有一定的参考价值。
题意:有n条平行x轴的线段,每条线段的起点为(ai,ci),终点为(bi,ci),且满足ai=b(i-1),从起点出发,每次可以往3个方向走,分别为 (x?+?1,?y?+?1), (x?+?1,?y), or (x?+?1,?y?-?1),且走的过程必须满足0>=y>=ci,求走到(k,0)有多少种走法
思路:dp+矩阵快速幂,
dp[i][0]=dp[i-1][0]+dp[i-1][1]
...........
dp[i][j]=dp[i-1][j]+dp[i-1][j+1]+dp[i-1][j-1]
...........
dp[i][c]=dp[i-1][c]+dp[i-1][c-1]
得到
dp[i][0] dp[i][1] ... dp[i][j] ... dp[i][c]
s矩阵 [ ]
dp[i+1][0] dp[i+1][1] ... dp[i+1][j] ... dp[i+1][c]
每段线段用一次矩阵快速幂
AC代码:
#include "iostream" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set" #include "map" #include "algorithm" #include "stdio.h" #include "math.h" #define ll long long #define bug(x) cout<<x<<" "<<"UUUUU"<<endl; #define mem(a) memset(a,0,sizeof(a)) using namespace std; const int N=20; ll M,Mod=1e9+7; struct Mat{ ll m[N][N]; Mat(){ mem(m); } Mat friend operator* (Mat a, Mat b){ Mat c; for(int i=0; i<M; i++) for(int j=0; j<M; j++) for(int k=0; k<M; k++) c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%Mod; return c; } }; Mat PowMod(Mat a, ll b){ Mat c; for(int i=0; i<M; ++i) c.m[i][i]=1; while(b){ if(b&1) c=c*a; a=a*a; b>>=1; } return c; } ll n,k,a[105],b[105],c[105]; int main(){ cin>>n>>k; for(int i=0; i<n; ++i){ cin>>a[i]>>b[i]>>c[i]; } Mat t; for(int i=0;i<16;i++) for(int j=i-1;j<=i+1;j++) if(j>=0&&j<16) t.m[i][j] = 1; Mat ans; ans.m[0][0]=1; for(int i=0; i<n; ++i){ k-=(b[i]-a[i]); M=c[i]+1; if(k>=0){ ans=ans*PowMod(t,b[i]-a[i]); } else{ k+=(b[i]-a[i]); ans=ans*PowMod(t,k); } } cout<<ans.m[0][0]; return 0; } /* 1 3 0 3 3 2 6 0 3 0 3 10 2 */
以上是关于Codeforces Round #420 E的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #420 (Div. 2)