zoukankan      html  css  js  c++  java
  • 【CF1487G】String Counting

    题目

    题目链接:https://codeforces.com/contest/1487/problem/G

    你有 (26) 个不同的字符,第 (i) 个字符有 (c_i) 个。
    你希望用这些字符,构造出一个字符串(每个字符在字符串中出现的个数不超过 (c_i)),使得这个字符串上不存在长度为奇数且大于 (1) 的回文串。求出方案数对 (998244353) 取模的结果。
    (nleq 400;frac{n}{3} < c_i leq n)

    思路

    显然等价于不存在两个位置 (i,i+2) 满足 (s_i=s_{i+2})
    这个 (c_i>frac{n}{3}) 意味着最多只有两个字符可能会超出限制,所以考虑容斥。
    (f[i][j][k][0/1/2][0/1/2]) 表示选到第 (i) 个位置,字符 (x) 出现 (j) 次,(y) 出现 (k) 次,第 (i-2,i-1) 位置的字符分别为 除 (x,y) 外的字符/字符 (x)/字符 (y) 的方案数。
    不用考虑字符 (x,y) 分别是什么,也不用考虑使用有没有超出 (c_x,c_y),只要求不存在两个位置 (i,i+2) 满足 (s_i=s_{i+2})
    这个东西大力分类讨论即可。注意当第 (i) 位填除 (x,y) 外的字符时,转移过来的权值可能为 (23)(24)
    然后记 (g[i][j]) 表示字符 (x) 使用至少 (i) 个,字符 (y) 使用至少 (j) 个的方案数。直接把 (f) 做一遍后缀和即可。
    容斥一下即可得到答案

    [g[0][0]-sum^{26}_{i=1}g[c_i+1][0]+sum^{26}_{i=1}sum^{26}_{j=i+1}g[c_i+1][c_j+1] ]

    (f) 数组滚动一下,时间复杂度 (O(n^3)),空间复杂度 (O(n^2))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=210,MOD=998244353;
    int n,ans,c[30],f[2][N][N][3][3],g[N][N];
    
    signed main()
    {
    	scanf("%d",&n);
    	for (int i=1;i<=26;i++)
    		scanf("%d",&c[i]);
    	f[0][0][0][0][0]=24*24;
    	f[0][1][0][1][0]=f[0][1][0][0][1]=f[0][0][1][0][2]=f[0][0][1][2][0]=24;
    	f[0][1][1][1][2]=f[0][1][1][2][1]=f[0][2][0][1][1]=f[0][0][2][2][2]=1;
    	for (int i=3;i<=n;i++)
    	{
    		int id=i&1;
    		memset(f[id],0,sizeof(f[id]));
    		for (int j=0;j<=n/2+1;j++)
    			for (int k=0;k<=n/2+1;k++)
    			{
    				f[id][j][k][0][0]=(23LL*f[id^1][j][k][0][0]+24LL*f[id^1][j][k][1][0]+24LL*f[id^1][j][k][2][0])%MOD;
    				f[id][j][k][1][0]=(23LL*f[id^1][j][k][0][1]+24LL*f[id^1][j][k][1][1]+24LL*f[id^1][j][k][2][1])%MOD;
    				f[id][j][k][2][0]=(23LL*f[id^1][j][k][0][2]+24LL*f[id^1][j][k][1][2]+24LL*f[id^1][j][k][2][2])%MOD;
    				if (j) f[id][j][k][0][1]=(f[id^1][j-1][k][0][0]+f[id^1][j-1][k][2][0])%MOD;
    				if (j) f[id][j][k][1][1]=(f[id^1][j-1][k][0][1]+f[id^1][j-1][k][2][1])%MOD;
    				if (j) f[id][j][k][2][1]=(f[id^1][j-1][k][0][2]+f[id^1][j-1][k][2][2])%MOD;
    				if (k) f[id][j][k][0][2]=(f[id^1][j][k-1][0][0]+f[id^1][j][k-1][1][0])%MOD;
    				if (k) f[id][j][k][1][2]=(f[id^1][j][k-1][0][1]+f[id^1][j][k-1][1][1])%MOD;
    				if (k) f[id][j][k][2][2]=(f[id^1][j][k-1][0][2]+f[id^1][j][k-1][1][2])%MOD;
    			}
    	}
    	for (int i=n/2+1;i>=0;i--)
    		for (int j=n/2+1;j>=0;j--)
    		{
    			ll sum=0;
    			for (int k=0;k<=8;k++)
    				sum=(sum+f[n&1][i][j][k/3][k%3])%MOD;
    			g[i][j]=(sum+g[i+1][j]+g[i][j+1]-g[i+1][j+1])%MOD;
    		}
    	ans=g[0][0];
    	for (int i=1;i<=26;i++)
    		if (c[i]+1<N) ans=(ans-g[c[i]+1][0])%MOD;
    	for (int i=1;i<=26;i++)
    		for (int j=i+1;j<=26;j++)
    			if (max(c[i],c[j])+1<N)
    				ans=(ans+g[c[i]+1][c[j]+1])%MOD;
    	printf("%d",(ans%MOD+MOD)%MOD);
    	return 0;
    }
    
  • 相关阅读:
    cnblog项目--20190309
    django js引入失效问题
    Python老男孩 day16 函数(六) 匿名函数
    Python老男孩 day16 函数(五) 函数的作用域
    Python老男孩 day15 函数(四) 递归
    Python老男孩 day15 函数(三) 前向引用之'函数即变量'
    Python老男孩 day15 函数(二) 局部变量与全局变量
    Python老男孩 day14 函数(一)
    Python老男孩 day14 字符串格式化
    Python老男孩 day14 集合
  • 原文地址:https://www.cnblogs.com/stoorz/p/14764394.html
Copyright © 2011-2022 走看看