矩阵基础1010 UVA 11651 矩阵快速幂+DP 好题,推荐

来源:互联网 发布:人工智能如何实现 编辑:程序博客网 时间:2024/05/21 07:07

题意:
问你分数为score的base进制的数有多少种
这个数必须满足相邻的数不相同而且没有前导零
分数是相邻的数的差的平方的和
思路:
dp[i][j]是分数为i时,以j结尾的数的个数
然后我们发现
每个dp[i][j]只被dp[(i-(base)*(base))~(i-1)][0~base-1]影响
我们就把这个区间里的数全部弄进矩阵里,就可以加速计算
时间复杂度大概是
O(150*150*150*log(1e9))因为有很多0,所以速度为更快

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#include<math.h>#include<queue>#include<stack>#include<string>#include<vector>#include<map>#include<set>using namespace std;#define lowbit(x) (x&(-x))typedef long long LL;const int maxn = 100005;const int inf=(1<<28)-1;#define Matrix_Size 155const LL MOD = 1LL<<32;struct Matrix {    int r, c;    LL mat[Matrix_Size][Matrix_Size];    Matrix (int r = 0, int c = 0) { set(r, c); }    void set(int r, int c) {        this->r = r;        this->c = c;        memset(mat, 0, sizeof(mat));    }    void clear()    {        memset(mat,0,sizeof(mat));    }    void output()    {        for(int i=0;i<r;++i)        {            for(int j=0;j<c;++j)            {                if(j) printf(" ");                printf("%lld",mat[i][j]);            }            printf("\n");        }        printf("\n");    }    Matrix operator * (const Matrix& u) {        Matrix ret(r, u.c);        for (int k = 0; k < c; k++) {            for (int i = 0; i < r; i++) {                if (mat[i][k] == 0)                    continue;                for (int j = 0; j < u.c; j++)                    ret.mat[i][j] = ((ret.mat[i][j] + mat[i][k] * u.mat[k][j]) % MOD+ MOD)%MOD;            }        }        return ret;    }};//res=(tmp^n)*retMatrix pow_M(Matrix tmp,Matrix ret,long long n){    while(n)    {        if(n&1)ret = tmp*ret;        tmp = tmp*tmp;        n>>=1;    }    return ret;}int dp[50][6];void GetDp(int base){    memset(dp,0,sizeof(dp));    for(int i=0;i<base;++i)        dp[0][i]=1;    for(int i=1;i<=(base-1)*(base-1);++i)    {        for(int j=0;j<base;++j)        {            for(int k=0;k<base;++k)            if(j!=k&&i>=(j-k)*(j-k))                dp[i][j]+=dp[i-(j-k)*(j-k)][k];        }    }}Matrix A,B;void GetMatrix(int base){    A.clear(),B.clear();    Size=(base-1)*(base-1)*base;    for(int i=1;i<=(base-1)*(base-1);++i)     for(int j=0;j<base;++j)     B.mat[(i-1)*base+j][0]=dp[i][j];    for(int i=base;i<Size;++i)        A.mat[i-base][i]=1;    int Now=Size-base;    for(int i=0;i<base;++i)    {        for(int j=0;j<base;++j)        if(j!=i)        {            A.mat[Now+i][(Now-(i-j)*(i-j)*(base))+j+base]=1;        }    }    //printf("%d %d\n",Size,base);    //A.output();printf("\n");}int main(){    int T,Case=0;    scanf("%d",&T);    while(T--)    {        int base;        LL score;        scanf("%d%lld",&base,&score);        printf("Case %d: ",++Case);        A.set((base-1)*(base-1)*base,(base-1)*(base-1)*base);        B.set((base-1)*(base-1)*base,1);        GetDp(base);        if(score<=(base-1)*(base-1))        {            LL Sum=0;            for(int i=1;i<base;++i)                Sum+=dp[score][i];            printf("%lld\n",Sum);            continue;        }        GetMatrix(base);        A=pow_M(A,B,score-(base-1)*(base-1));        LL Sum=0;        for(int i=1;i<base;++i)        {            Sum+=A.mat[((base-1)*(base-1)-1)*base+i][0];            Sum%=MOD;        }        printf("%lld\n",Sum);    }    return 0;}
0 0
原创粉丝点击