20201029模拟赛总结

T1

看到这题第一眼感觉这不是直接暴力就可以吗……

尽管如此,我还是莫名其妙的写了一个 (KMP) 尽管什么也没有用到,然后它跑 (RE) 了导致 (60pts) 溜了。

其实我们只需要循环比较,比较长度是较长字符串的二倍即可啦!

T2

这题的根号居然是实数意义下的,我以为是整数意义下直接懵逼爆零滚粗 qwq 。

我们化简 (sqrt {m} = ksqrt b) , 发现若要等式成立那么 (sqrt x) 必须是 (sqrt b) 的倍数。

那么也就是说我们要求出数列 (a_1 , a_2 , a_3 , dots , a_{n-1} , a_n) 使得 (sumlimits_{i=1}^n a_i = k) 即可,数量可用插板法求解。

T3

这道题一眼就发现不可做,然而我却成功的在样例特水无大样例的情况下通过了这道题!!!

我们考虑 (DP) ,设状态 (dp[i][j][k]) 为 前 (i) 个字母现在匹配到第 (j) 个句式的第 (k) 个单词的方案数,然后在单词结尾处转移即可,可以使用 AC自动机 处理。

code:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define ll long long
using namespace std;

int read()
{
	int a = 0,x = 1;char ch = getchar();
	while(ch > '9' || ch < '0') {if(ch == '-') x = -1;ch = getchar();}
	while(ch >= '0' && ch <= '9') {a = a*10 + ch-'0';ch = getchar();}
	return a*x;
}
const int N=1007,P=1000000007;
int n,m;
char s[N];
int ch[N][27],vis[N],p[N],len[N],nxt[N],cnt;
bool ins[N][11];
void add(int num)
{
	int t = 1;len[num] = strlen(s+1);
	for(int i = 1;i <= len[num];i ++){
		if(!ch[t][s[i]-'a']) ch[t][s[i]-'a'] = ++cnt;
		t = ch[t][s[i]-'a'];
	}
	if(!vis[t]) vis[t] = num;
	int tmp = read();
	for(int i = 1;i <= tmp;i ++) {
		int a = read();
		if(!ins[vis[t]][a]) {p[num] ++,ins[vis[t]][a] = 1;}
	}
}
queue<int>q;
void init()
{
	for(int i = 0;i < 26;i ++) ch[0][i] = 1;
	q.push(1);
	while(!q.empty()) {
		int u = q.front();q.pop();
		printf("%d
",u);
		for(int i = 0;i < 26;i ++) {
			if(!ch[u][i]) ch[u][i] = ch[nxt[u]][i];
			else {
				nxt[ch[u][i]] = ch[nxt[u]][i];
				q.push(ch[u][i]);
			}
		}
	//	getchar();
	}
}

int num[12],wo[12][12];
ll dp[N][12][12],f[N];

#define fa nxt
int find(int s,int i)
{
	if(!s) return s;
	if(!vis[s]) return fa[s] = find(fa[s],i);
	find(fa[s],i);
	for(int j = 1;j <= m;j ++) {
		for(int k = 1;k <= num[j];k ++) {
			if(ins[vis[s]][wo[j][k]]) {
				if(k > 1) {
					(dp[i][j][k] += dp[i-len[vis[s]]][j][k-1]) %= P;
				} else (dp[i][j][k] += f[i-len[vis[s]]]) %= P;
			}	
		}
	}
	return s;
}
#undef fa

int main()
{
	freopen("word.in","r",stdin);
	freopen("word.out","w",stdout);
	n = read(),m = read(),cnt = 1;
	for(int i = 1;i <= n;i ++) {
		scanf("%s",s+1);
		add(i);
	}
	init();
	for(int i = 1;i <= m;i ++) {
		num[i] = read();
		for(int j = 1;j <= num[i];j ++) wo[i][j] = read();
	}
	scanf("%s",s+1);int l = strlen(s+1);
	f[0] = 1;for(int i = 1,t = 1;i <= l;i ++) {
		t = ch[t][s[i]-'a'];find(t,i);
		for(int j = 1;j <= m;j ++) (f[i] += dp[i][j][num[j]]) %= P;
	}
	printf("%lld",f[l]);
	return 0;
}
原文地址:https://www.cnblogs.com/nao-nao/p/13898683.html