Codeforces Round #420 (Div. 2) E. Okabe and El Psy Kongroo dp+矩阵快速幂

来源:互联网 发布:入门c语言 编辑:程序博客网 时间:2024/05/18 03:40

题目链接:点击打开链接

题意:

在一个二维xoy第一象限平面上(x,y必须保持非负),你一开始在原点(0,0),每一次可以从(x,y)往右跳到(x+1,y),也可以向右上角跳到(x+1,y+1),也可以向右下角跳到(x+1,y-1),然后还有n条平行于x轴的线段(a,b,c),分别在(a,c)-(b,c)上,当你的横坐标在[a,b]区间时,y坐标不能超过c,问有多少种方案到达(k,0)。结果对10^9+7取余
(1<=n<=100,0<=c<=15,0<=a,b,k<=10^18,a[i]=b[i-1],a[0]=0)
思路:

dp+矩阵快速幂

比较裸的dp+矩阵快速幂,因为这里k为1e18,所以几乎只能用矩阵快速幂来做了。

朴素的dp,dpij表示走到(i, j)时的方案数,

则 状态方程为,if(j+1 <= b[k]) dp[i+1][j+1] += dp[i][j];

                             if(j-1 >= 0) dp[i+1][j-1] += dp[i][j];

                             dp[i+1][j] += dp[i][j];

然后可以构造出15*15(ci<=15)的矩阵,把状态转移到矩阵上,然后对于每个a[k]、b[k]、c[k]跑一次快速幂即可。

此外注意a[k],b[k],以及快速幂的参数到是LL。

复杂度 O(n*(15)^3*log(k))


#include <cstdio>#include <cstring>#include <cmath>#include <iostream>using namespace std;#define ll long long#define N 25#define maxn 300ll mod=1000000007;ll n,k;struct Matrix{    ll r,c;    ll m[N][N];    Matrix(){}    Matrix(ll r,ll c):r(r),c(c){}    Matrix operator *(const Matrix& B)//乘法    {        Matrix T(r,B.c);        for(int i=1;i<=T.r;i++)        {            for(int j=1;j<=T.c;j++)            {                ll tt = 0;                for(int k=1;k<=c;k++)                    tt +=( m[i][k]*B.m[k][j]) % mod;                T.m[i][j] = tt % mod;            }        }        return T;    }Matrix operator =(const Matrix& B)//复制    {        for(int i=1;i<=r;i++)        {            for(int j=1;j<=c;j++)            {                m[i][j] = B.m[i][j];            }        }    }    Matrix operator +(const Matrix& B)//加法    {        for(int i=1;i<=r;i++)        {            for(int j=1;j<=c;j++)            {                m[i][j]+= B.m[i][j];            }        }    }    Matrix Unit(ll h) // 对角线矩阵    {        Matrix T(h,h);        memset(T.m,0,sizeof(T.m));        for(int i=1;i<=h;i++)            T.m[i][i] = 1;        return T;    }    Matrix Pow(ll n)  //矩阵幂    {        Matrix P = *this,Res = Unit(r);        while(n!=0)        {            if(n&1)                Res =Res*P;            P = P*P;            n >>= 1;        }        return Res;    }    void Print()//输出    {        for(int i=1;i<=r;i++)        {            for(int j=1;j<=c;j++)                printf("%d ",m[i][j]);            printf("\n");        }    }}Single;ll u[maxn],v[maxn],h[maxn];int main(){while(~scanf("%lld%lld",&n,&k)){for(int i=0;i<n;i++){scanf("%lld%lld%lld",&u[i],&v[i],&h[i]);h[i]++;}Matrix a(17,17),b(1,17);memset(b.m,0,sizeof b.m);b.m[1][1]=1;for(int i=0;i<n;i++){memset(a.m,0,sizeof a.m);for(int j=1;j<=h[i];j++){if(j+1<=h[i]){a.m[j][j+1]=1;}if(j-1>=1){a.m[j][j-1]=1;}a.m[j][j]=1;}if(k<v[i])b=b*a.Pow(k-u[i]);elseb=b*a.Pow(v[i]-u[i]);}cout<<b.m[1][1]<<endl;//printf("%lld\n",b.m[1][1]);}return 0;}



阅读全文
0 0
原创粉丝点击