传送门:点击打开链接
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3929 Accepted Submission(s): 1147
题意:给出n个单词。问长度不超过m的串中,至少包含上述的至少一个单词的串的数目,对2^64取MOD
思路:这道题和POJ 2278比较相似,没有做过的请先参考http://blog.csdn.net/w703710691d/article/details/43271693
与POJ 2278最大的不同的,这道题要求得是长度不超过m的串。就要求得长度为1、2、3……m的符合要求串。可以参照POJ 2278的思路,先求出不符合的串,在用总数减去这个值,就得到了答案。下面设矩阵为A.中间会用到求A+A^2+A^3+……A^m【记为X】和26+26^2+26^3……+26^m次方的值。可以参考二分幂的方法。先求出(A+A^2+A^3……A^(m/2)【记为B】和A^(m/2)的值。那么X=(A^(m/2)+E)*B。E为单位阵。算数的也是同样的方法。将运算过程中的变量和矩阵的元素定义为unsigned __int64,就能实现自动对2^64自动取MOD
代码:
#pragma comment(linker, "/STACK:102400000,102400000")
#include
#include
#define SIGMA_SIZE 26
#define maxn 40
#include
#define uLL unsigned __int64
using namespace std;
int ch[maxn][SIGMA_SIZE];
int val[maxn];
int last[maxn], f[maxn];
int cnt;
inline int idx(char c)
{
return c - 97;
}
void insert(char s[])
{
int len = strlen(s);
int u = 0;
for (int i = 0; i bin(Matrix a, int k)
{
pair tmp, res;
if (k == 0)
{
return make_pair(ZERO(a.r), ONE(a.r));
}
else if (k == 1)
return make_pair(a, a);
tmp = bin(a, k >> 1);
res.first = (tmp.second + ONE(a.r))*tmp.first;
res.second = tmp.second*tmp.second;
if (k & 1)
{
res.second = res.second*a;
res.first = res.first + res.second;
}
return res;
}
bool vis[maxn];
int mp[maxn][maxn];
void bfs()
{
memset(vis, 0, sizeof(vis));
vis[0] = 1;
queueq;
q.push(0);
while (!q.empty())
{
int u = q.front();
q.pop();
for (int i = 0; i<26; i++)
{
int p = u;
while (p&&!ch[p][i]) p = f[p];
p = ch[p][i];
if (val[p]) continue;
if (last[p]) continue;
mp[u][p]++;
if (!vis[p]) q.push(p);
vis[p] = 1;
}
}
}
pair bin(uLL a, int k)
{
if (k == 1) return make_pair(a, a);
else if (k == 0) return (make_pair(0, 1));
pairtmp, res;
tmp = bin(a, k >> 1);
res.first = (tmp.second + 1)*tmp.first;
res.second = tmp.second*tmp.second;
if (k & 1)
{
res.second = res.second*a;
res.first = res.first + res.second;
}
return res;
}
void slove(uLL m)
{
memset(mp, 0, sizeof(mp));
bfs();
Matrix tmp;
tmp.r = cnt;
tmp.c = cnt;
for (int i = 0; i <= cnt; i++)
for (int j = 0; j <= cnt; j++) tmp.g[i][j] = mp[i][j];
pair res;
res = bin(tmp, m);
uLL ans = 0;
for (int i = 0; i <= cnt; i++) ans += res.first.g[0][i];
ans = bin(26, m).first - ans;
printf("%I64u\n", ans);
}
void getFail()
{
queueq;
f[0] = 0;
for (int c = 0; c
可能会栈溢出,所以我直接交了C++