Codeforces 300D Painting Square 题解

来源:互联网 发布:海岛奇兵升船数据 编辑:程序博客网 时间:2024/05/18 20:46

题意

一个四周围都是黑色的由n行n列小格子组成的方块,每次可以选择一个已经由黑框包围的正方形将它的一行一列涂黑要求分割出的部分还都是正方形,问涂k次可以有多少种不同的涂法

思路

因为只能分割成正方形,所以肯定是每一次涂最中间的行和最中间的列,那么可以涂的次数就是不断对n减一除以2看能做多少层,至于答案就用dp计算,从小往大,先左右变成二倍,再上下变成二倍,ans[i][j]=(ans[i][j]+(temp[k]*temp[j-1-k])%mod)%mod,ans[i][j]表示涂i层已经涂了j次的涂法数量,temp[k]表示上下一半那么大涂k次的方法数,temp[j]=(temp[j]+(ans[i][k]*ans[i][j-k])%mod)%mod,这个就是在做左右的延展,左边涂k次,右边涂j-k次,一共就涂了j次,最后ans[层数][k]就是答案

代码

#include<cstdio>#define mod 7340033long long ans[31][1001],temp[1001];int main(){    long long q,n,k,cnt;    ans[0][0]=1;    temp[0]=1;    for(long long i=1;i<=30;i++)    {        ans[i][0]=1;        for(long long j=1;j<=1000;j++)            for(long long k=0;k<j;k++)                ans[i][j]=(ans[i][j]+(temp[k]*temp[j-1-k])%mod)%mod;        for(long long j=1;j<=1000;j++)            temp[j]=0;        temp[0]=1;        for(long long j=1;j<=1000;j++)            for(long long k=0;k<=j;k++)                temp[j]=(temp[j]+(ans[i][k]*ans[i][j-k])%mod)%mod;    }    scanf("%I64d",&q);    for(long long i=0;i<q;i++)    {        scanf("%I64d%I64d",&n,&k);        cnt=0;        while((n%2)&&n>1)        {            cnt++;            n/=2;        }        printf("%I64d\n",ans[cnt][k]);    }    return 0;}
原创粉丝点击