Inverse Coloring(奇怪的dp)

You are given a square board, consisting of nn rows and nn columns. Each tile in it should be colored either white or black.

Let's call some coloring beautiful if each pair of adjacent rows are either the same or different in every position. The same condition should be held for the columns as well.

Let's call some coloring suitable if it is beautiful and there is no rectangle of the single color, consisting of at least kk tiles.

Your task is to count the number of suitable colorings of the board of the given size.

Since the answer can be very large, print it modulo 998244353998244353.

Input

A single line contains two integers nn and kk (1≤n≤5001≤n≤500, 1≤k≤n21≤k≤n2) — the number of rows and columns of the board and the maximum number of tiles inside the rectangle of the single color, respectively.

Output

Print a single integer — the number of suitable colorings of the board of the given size modulo 998244353998244353.

思路:其实只要确定一行和一列就可以确定整个矩阵。而行和列长度一样,所以只要计算出一行的情况就行。

dp[i][j]表示前i个里,最长相等字段的个数为j,但是这样不方便写转移。

所以,改成dp[i][j]表示前i个,最长字段不超过j的方案树,最后差分一下dp[i][j],dp[i][j-1],就是我们想要的

dp[i][j]+=dp[i-k][min(i-k,j)];

代码:

#include <bits/stdc++.h>
#define maxn 1010
using namespace std;
#define mod 998244353
typedef long long ll;
int k,n;
ll dp[maxn][maxn];
int main(int argc, char const *argv[])
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
   //cin>>n>>k;
   scanf("%d%d",&n,&k);
    //memset(dp,0,sizeof(dp));
    dp[0][0]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            for(int p=1;p<=j;p++)
            {
                dp[i][j]=(dp[i][j]+dp[i-p][min(j,i-p)])%mod;
            }
        }
	}
    for(int i=n;i>=1;i--)
    {
        dp[n][i]=(dp[n][i]-dp[n][i-1]+mod)%mod;
    }
    ll ans=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j*i<k;j++)
        {
			ans=(ans+dp[n][i]*dp[n][j]%mod)%mod;
        }
    }
    ans=(ans*2)%mod;
    printf("%lld\n",ans);
    return 0;
}

奇怪的是,我用cnt[i]来记录差分时,结果却错了...

代码:

#include <bits/stdc++.h>
#define maxn 1010
using namespace std;
#define mod 998244353
typedef long long ll;
int k,n;
ll dp[maxn][maxn];
int main(int argc, char const *argv[])
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    scanf("%d%d",&n,&k);
    //memset(dp,0,sizeof(dp));
    dp[0][0]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            for(int p=1;p<=j;p++)
            {
                dp[i][j]=(dp[i][j]+dp[i-p][min(i-p,j)])%mod;
            }
        }
	}
    for(int i=n;i>=1;i--)
    {
        dp[n][i]=(dp[n][i]-dp[n][i-1]+mod)%mod;
    }
    ll ans=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j*i<k;j++)
        {
	ans=(ans+dp[n][i]*dp[n][j]%mod)%mod;
        }
    }
    ans=(ans*2ll)%mod;
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40774175/article/details/82155109