Codeforces 821E Okabe and El Psy Kongroo
阿新 • • 發佈:2017-11-07
eof return log include class def blog roo bit
題意:我們現在位於(0,0)處,目標是走到(K,0)處。每一次我們都可以從(x,y)走到(x+1,y-1)或者(x+1,y)或者(x+1,y+1)三個位子之一。現在一共有N段線段,每條線段都是平行於X軸的。我們如果此時x是在這段線段之內的話,我們此時走到的點(x,y)需要滿足0<=y<=Ci.現在保證一段線段的終點,一定是下一段線段的起點。問我們從起點走到終點的行走方案數。
dp方程比較顯然:dp[i][j]+=dp[i-1][j]+dp[-1][j-1]+dp[i-1][j+1]
之後構造一個如下的矩陣即可:
110000..0
011100..0
...
000.....111
同時註意一下矩陣的初始化,因此WA了很多次....
#include<bits/stdc++.h> using namespace std; typedef __int64 LL; const LL MODD=1000000007; struct mat{ LL a[17][17]; void init(int t){ for(int i=0;i<=t;i++)a[i][i]=1; } void clear(){ memset(a,0,sizeof(a)); } }; int n; LL k; mat mul(mat x,mat y,int t){ mat h; h.clear();for(int i=0;i<=t;i++) for(int j=0;j<=t;j++) for(int k=0;k<=t;k++){ h.a[i][j]+=(x.a[i][k]%MODD*y.a[k][j]%MODD)%MODD; h.a[i][j]%=MODD; } return h; } mat pw(mat x,LL t,int l){ mat b; b.clear(); b.init(l); for(;t;t>>=1,x=mul(x,x,l)) if(t&1)b=mul(b,x,l); return b; } int main(){ mat p,a,ans; p.clear(); ans.clear(); for(int i=0;i<=15;i++) for(int j=max(0,i-1);j<=min(i+1,15);j++) p.a[i][j]=1; scanf("%d%I64d",&n,&k); a.clear(); a.a[0][0]=1; bool flag=false; for(int i=1;i<=n;i++){ LL l,r; int t; scanf("%I64d%I64d%d",&l,&r,&t); if(r>k){r=k;flag=true;} ans=pw(p,r-l,t); for(int j=t+1;j<=15;j++)a.a[j][0]=0; ans=mul(ans,a,t); for(int j=0;j<=t;j++)a.a[j][0]=ans.a[j][0]; if(flag)break; } printf("%I64d\n",ans.a[0][0]); return 0; }
Codeforces 821E Okabe and El Psy Kongroo