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;
}