20201029模拟赛总结

T1

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

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

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

T2

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

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

那么也就是说我们要求出数列 \(a_1 , a_2 , a_3 , \dots , a_{n-1} , a_n\) 使得 \(\sum\limits_{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\n",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;
}
posted @ 2020-10-29 19:16  nao-nao  阅读(71)  评论(0编辑  收藏  举报