【题解】UVA1633:ディスレクシアゴラム


長さがkkであることが保証されている限り、@ vjudgekまたはk + 1 k + 1k+1の回文を
押すと、最後のkkを保存できますKビットステータス、転送するたびに妥当かどうかを判断するだけ

コード:

#include <bits/stdc++.h>
#define maxn 410
#define maxm 2010
#define qy 1000000007
using namespace std;
int power[25], n, m, dp[maxn][maxm];

inline int read(){
    
    
	int s = 0, w = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
	return s * w;
}

bool calc(int x, int y){
    
     return !(x > 0 && y > 0 || x == 0 && y == 0); }

bool check(int x, int y){
    
    
	int flag = 0;
	if (calc(x & power[m - 1], y)) flag = 1;
	if (!flag)
		for (int i = m - 1; i; --i)
			if (calc(x & power[i - 1], x & power[m - i - 1])){
    
     flag = 1; break; }
	return flag;
}

bool check1(int x, int y){
    
    
	int flag = 0;
	if (calc(x & power[m - 2], y)) flag = 1;
	if (!flag){
    
    
		for (int i = m - 2; i; --i)
			if (calc(x & power[i - 1], x & power[m - 1 - i - 1])){
    
     flag = 1; break; }
	}
	return flag;
}

int main(){
    
    
	int Q = read();
	power[0] = 1;
	for (int i = 1; i <= 20; ++i) power[i] = power[i - 1] << 1;
//	m = 3; printf("%d\n", check1(2, 1));
	while (Q--){
    
    
		n = read(), m = read();
		if (m < 2){
    
     puts("0"); continue; }
	//	printf("%d\n", ((2 << 1) | 1) & (power[m] - 1));
		for (int i = 1; i <= n; ++i)
			for (int j = 0; j <= power[m] - 1; ++j) dp[i][j] = 0;
		dp[1][0] = dp[1][1] = 1;
		for (int i = 1; i < n; ++i)
			for (int j = 0; j <= power[min(m, i)] - 1; ++j){
    
    
			//	printf("modest%d\n", dp[i][j]);
				for (int k = 0; k <= 1; ++k)
					if (i < m - 1 || (i == m - 1 && check1(j, k)) || i >= m && check1(j, k) && check(j, k)){
    
    
						if ((dp[i + 1][((j << 1) | k) & (power[m] - 1)] += dp[i][j]) >= qy)
							dp[i + 1][((j << 1) | k) & (power[m] - 1)] -= qy;
//						printf("dp[%d][%d]=%d\n", i + 1, ((j << 1) | k) & (power[m] - 1), dp[i + 1][((j << 1) | k) & (power[m] - 1)]);
					}
			}
		int ans = 0;
		for (int i = 0; i < power[min(m, i)]; ++i) if ((ans += dp[n][i]) >= qy) ans -= qy;
		printf("%d\n", ans);
	}
	return 0;
}

おすすめ

転載: blog.csdn.net/ModestCoder_/article/details/108562156