1. 程式人生 > >Codeforces Round #420 E

Codeforces Round #420 E

-1 turn log sizeof mes cout ref long targe

Okabe and El Psy Kongroo

題意:有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