C ++ 11(应该达到11或12)
目前,这是单线程的。
编译:
g++ -std=c++11 -O2 -march=native feersum.cpp
#include <iostream>
#include <unordered_set>
#include <vector>
#include <unordered_map>
#include <string.h>
using seq = uint64_t;
using bitvec = uint32_t;
using seqset = std::unordered_set<seq>;
using std::vector;
#define popcount __builtin_popcount
#define MAX_N_BITS 4
bitvec leading(bitvec v, int n) {
return v & ((1U << n) - 1);
}
bitvec trailing(bitvec v, int n, int total) {
return v >> (total - n);
}
bitvec maxP(int n) {
return 1 << (n - 1); // ~P, ~T symmetry
}
void prefixes(int n, int pre, int P, seqset& p) {
p.clear();
for (bitvec pref = 0; pref < (1U << pre); pref++) {
seq s = 0;
for (int i = 0; i < pre; i++) {
seq ham = popcount(trailing(pref, pre - i, pre) ^ leading(P, pre - i));
s |= ham << i * MAX_N_BITS;
}
p.insert(s);
}
}
vector<seqset> suffixes(int n, int suf, int off) {
vector<seqset> S(maxP(n));
for (bitvec P = 0; P < maxP(n); P++) {
for (bitvec suff = 0; suff < (1U << suf); suff++) {
seq s = 0;
for (int i = 0; i < suf; i++) {
seq ham = popcount(leading(suff, i + 1) ^ trailing(P, i + 1, n));
s |= ham << (off + i) * MAX_N_BITS;
}
S[P].insert(s);
}
}
return S;
}
template<typename T>
void mids(int n, int npre, int nsuf, int mid, bitvec P, T& S, const seqset& pre) {
seq mask = (1ULL << (npre + 1) * MAX_N_BITS) - 1;
for(bitvec m = 0; m < 1U << mid; m++) {
int pc = popcount(P ^ m);
if(pc * 2 > n) continue; // symmetry of T -> ~T : replaces x with n - x
seq s = (seq)pc << npre * MAX_N_BITS;
for(int i = 0; i < npre; i++)
s |= (seq)popcount(trailing(P, n - npre + i, n) ^ leading(m, n - npre + i)) << i * MAX_N_BITS;
for(int i = 0; i < nsuf; i++)
s |= (seq)popcount(leading(P, mid - 1 - i) ^ trailing(m, mid - 1 - i, mid)) << (npre + 1 + i) * MAX_N_BITS;
for(seq a: pre)
S[(s + a) & mask].insert(P | (s + a) << n);
}
}
uint64_t f(int n) {
if (n >= 1 << MAX_N_BITS) {
std::cerr << "n too big";
exit(1);
}
int tlen = 2*n - 1;
int mid = n;
int npre = (tlen - mid) / 2;
if(n>6) --npre;
int nsuf = tlen - npre - mid;
seqset preset;
auto sufs = suffixes(n, nsuf, npre + 1);
std::unordered_map<seq, std::unordered_set<uint64_t>> premid;
for(bitvec P = 0; P < maxP(n); P++) {
prefixes(n, npre, P, preset);
mids(n, npre, nsuf, mid, P, premid, preset);
}
uint64_t ans = 0;
using counter = uint8_t;
vector<counter> found((size_t)1 << nsuf * MAX_N_BITS);
counter iz = 0;
for(auto& z: premid) {
++iz;
if(!iz) {
memset(&found[0], 0, found.size() * sizeof(counter));
++iz;
}
for(auto& pair: z.second) {
seq s = pair >> n;
uint64_t count = 0;
bitvec P = pair & (maxP(n) - 1);
for(seq t: sufs[P]) {
seq suff = (s + t) >> (npre + 1) * MAX_N_BITS;
if (found[suff] != iz) {
++count;
found[suff] = iz;
}
}
int middle = int(s >> npre * MAX_N_BITS) & ~(~0U << MAX_N_BITS);
ans += count << (middle * 2 != n);
}
}
return ans;
}
int main() {
for (int i = 1; ; i++)
std::cout << i << ' ' << f(i) << std::endl;
}