zoukankan      html  css  js  c++  java
  • UVA1633 Dyslexic Gollum

    传送门


    翻译:输入正整数(n)(k(1 leqslant n leqslant 400, 1 leqslant k leqslant 10)),求长度为(n)的01串中有多少个不含长度至少为(k)的回文连续子串。比如(n=k=3)时只有4个串满足条件:001, 011, 100, 110。


    这题的关键在于:如果字符串中不含有长度为(k)的回文串,那么也一定不含有长度大于(k)的回文串。因为长度大于(k)的回文串,会在检查他的子串时就被筛去了。


    看到(k)很小,想到状压dp,令(dp[i][S])表示长度为(i)的字符串中,后(k+1)位的字符串是(S)时的合法的字符串个数。
    为什么是(k+1)位,因为奇偶回文串的关系,长度为(k)的回文串只能筛掉长度为(k+2,k+4 ldots)的回文串。


    首先预处理出来长度为(k+1)的合法串,即不含有长度为(k)(k+1)的回文子串的01串。
    然后就可以dp了:对于当前第(i)位,枚举后(k+1)位状态,再枚举第(i+1)位是0还是1,然后拼成新的(k+1)位,转移到(i+1)


    最后的答案就是(sum dp[n][S])


    代码里把(K > n)(K=n)的情况特判了一下,写的可能有点啰嗦。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<queue>
    #include<assert.h>
    #include<ctime>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define In inline
    #define forE(i, x, y) for(int i = head[x], y; ~i && (y = e[i].to); i = e[i].nxt)
    typedef long long ll;
    typedef double db;
    const int INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    const int maxn = 405;
    const int maxs = 2050;
    const ll mod = 1e9 + 7;
    In ll read()
    {
    	ll ans = 0;
    	char ch = getchar(), las = ' ';
    	while(!isdigit(ch)) las = ch, ch = getchar();
    	while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
    	if(las == '-') ans = -ans;
    	return ans;
    }
    In void write(ll x)
    {
    	if(x < 0) x = -x, putchar('-');
    	if(x >= 10) write(x / 10);
    	putchar(x % 10 + '0');
    }
    In void MYFILE()
    {
    #ifndef mrclr
    	freopen(".in", "r", stdin);
    	freopen(".out", "w", stdout);
    #endif
    }
    
    int n, m, K;
    
    ll dp[maxn][maxs];
    bool v[maxs];
    
    In bool judge(int x, int len)
    {
    	bool flg1 = 0, flg2 = 0, flg3 = 0;
    	for(int i = 0, j = len - 1; i < j; ++i, --j)
    		if(((x >> i) & 1) ^ ((x >> j) & 1)) flg1 = 1;
    	for(int i = 0, j = len - 2; i < j; ++i, --j)
    		if(((x >> i) & 1) ^ ((x >> j) & 1)) flg2 = 1;
    	for(int i = 1, j = len - 1; i < j; ++i, --j)
    		if(((x >> i) & 1) ^ ((x >> j) & 1)) flg3 = 1;
    	return (flg1 && flg2 && flg3);
    }
    In void init()
    {
    	Mem(dp, 0);
    	m = 1 << (K + 1);
    	for(int i = 0; i < m; ++i) v[i] = judge(i, K + 1);
    }
    
    In int ADD(ll a, ll b) {return a + b < mod ? a + b : a + b - mod;}
    
    In void solve()
    {
    	for(int i = 0; i < m; ++i) dp[K + 1][i] = v[i];
    	for(int i = K + 2; i <= n; ++i)
    		for(int j = 0; j < m; ++j)	
    		{
    			int tp = (j << 1) & (m - 1);
    			if(v[tp]) dp[i][tp] = ADD(dp[i][tp], dp[i - 1][j]);
    			if(v[tp | 1]) dp[i][tp | 1] = ADD(dp[i][tp | 1], dp[i - 1][j]);
    		}
    	ll ans = 0;
    	for(int i = 0; i < m; ++i) ans = ADD(ans, dp[n][i]);
    	write(ans), enter;
    }
    
    In ll quickpow(ll a, ll b)
    {
    	ll ret = 1;
    	for(; b; b >>= 1, a = a * a % mod)
    		if(b & 1) ret = ret * a % mod;
    	return ret;
    }
    
    In int work0()
    {
    	ll ret = 0;
    	for(int i = 0; i < (1 << K); ++i)
    	{
    		bool flg = 0;
    		for(int j = 0, k = n - 1; j < k && !flg; ++j, --k)
    			if(((i >> j) & 1) ^ ((i >> k) & 1)) flg = 1;
    		ret += flg;
    	}
    	return ret;
    }
    
    int main()
    {
    //	MYFILE();
    	int T = read();
    	while(T--)
    	{
    		n = read(), K = read();
    		if(K > n) write(quickpow(2, n)), enter;
    		else if(K == n) write(work0()), enter;
    		else init(), solve();
    	}
    	return 0;
    }
    
  • 相关阅读:
    Java多线程学习---------超详细总结(java 多线程 同步 数据传递 )
    类的高级特性——抽象类
    多态
    继承、继承中的重写
    接口interface、实现接口implements
    “==”运算符与equals()
    静态成员
    对象
    属性和行为(成员变量和成员方法)
    字符串生成器
  • 原文地址:https://www.cnblogs.com/mrclr/p/13839372.html
Copyright © 2011-2022 走看看