注意到长度为 $n$ 的合法(即 $f_v$ 不为 0)的 $v$ 的数量远小于 $2^n$,下表给出了对于每一个 $n$ 合法的 $v$ 数量(注意这个数量是和 $m$ 无关的,当然 $m=1$ 除外,证明见 Leo J. Guibas and Andrew M. Odlyzko. Periods in strings. J. of Combinatorial Theory series A, 30:19–42, 1981. 的 Section 5 Theorem 5.1),具体详见 OEIS A005434:
constint N = 21; constint V = 1 << 20; constint mod = 1000000007;
typedeflonglong ll;
int n, m, cur_len; bool ok[V];
inlinevoidupd(int &x){ x += (x >> 31) & mod; } inlineintpro(int x){ return x + ((x >> 31) & mod); } inline ll fast_pow(ll x, int p = mod - 2){ ll ret = 1; while (p) { if (p & 1) (ret *= x) %= mod; (x *= x) %= mod; p >>= 1; } return ret; } template<class T> inlinevoidfill_zero(T *first, T *last){ memset(first, 0, sizeof(T) * (last - first)); }
// 找到所有可行的 v 并把他们存到 ok 中 voiddfs(int x = 1, int j = 0){ staticint pre[N], a[N]; if (x == cur_len + 1) { int x = cur_len; int ret = 0; while (x) { ret |= 1 << (cur_len - x); x = pre[x]; } ok[ret] = 1; return; } for (int &c = a[x] = 0; c < 2; ++c) { int nj = j; while (nj && c != a[nj + 1]) nj = pre[nj]; if (x != 1 && c == a[nj + 1]) ++nj; pre[x] = nj;
dfs(x + 1, nj); } }
// 一种 O(n) 找出一种 v 中自由元个数的算法 // 参考 http://www.lirmm.fr/~rivals/RESEARCH/PERIOD/Web-NFC.pdf inlineintnfc(int v){ int l = 0, ret = 0; while (true) { constint n = cur_len - l; int i = 1; while (i < n && !((v >> (l + i)) & 1)) ++i; if (i == n) return n + ret; if (i == 1) return1 + ret; if (i <= (n >> 1)) l += n - i - n % i; else { ret += i * 2 - n; l += i; } } return ret; }