1. 程式人生 > >Codeforces 821E Okabe and El Psy Kongroo

Codeforces 821E Okabe and El Psy Kongroo

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