Codeforce821E Okabe and El Psy Kongroo

题意:给n条水平线段点终点高度,只能右上方向走,向右走,右下方向走,只能在第一象限及坐标轴上线段下面运动问到(K,0)有多少种方案

题解:可以推出DP式子,对每一条线段使用快速幂

#include <bits/stdc++.h>
#define maxn 20
using namespace std;
long long mod = 1e9+7, len=20, n, k, sta[110], en[110], c[110];
struct mat{
    long long m[maxn][maxn];//注意初始化
    mat friend operator*(mat a,mat b){
        mat d;
        memset(d.m, 0, sizeof(d.m));
        for(int i=0;i<len;i++)
            for(int j=0;j<len;j++)
                for(int k=0;k<len;k++)
                d.m[i][j] = (d.m[i][j]%mod+(a.m[i][k]*b.m[k][j])%mod)%mod;
        return d;
    }
};
mat f(mat x,long long num){
    mat t;
    memset(t.m, 0, sizeof(t.m));
    for(int i=0;i<len;i++) t.m[i][i] = 1;
    while(num){
        if(num&1) t = t*x;
        x = x*x;
        num >>= 1;
    }
    return t;
}
int main(){
    int i,j;
    mat s, ss;
    memset(s.m, 0, sizeof(s.m));
    memset(ss.m, 0, sizeof(ss.m));
    s.m[0][0] = 1;
    for(i=0;i<len;i++)
        for(j=i-1;j<=i+1;j++)
            if(j>=0&&j<len)
                ss.m[i][j] = 1;
    cin>>n>>k;
       for(i=0;i<n;i++) cin>>sta[i]>>en[i]>>c[i];
       i = 0;
    while(i<n&&k>=en[i]){
           len = c[i]+1;
        s = s*f(ss, en[i]-sta[i]);
           i++;
    }
    len = c[i]+1;
    s = s*f(ss, k-en[i-1]);
    cout<<s.m[0][0]<<endl;
    return 0;
}

 

posted on 2017-07-01 16:47  2855669158  阅读(332)  评论(0编辑  收藏  举报

导航