我们先按长度分类对于当前处理的长度k, 我们令 F[ i ] 为有长度为 i 的循环节的方案数。
然后容斥出f[ i ] 表示最小循环节是 i 的方案数, 然后加起来。
#include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ALL(x) (x).begin(), (x).end() #define fio ios::sync_with_stdio(false); cin.tie(0); using namespace std; const int N = 100 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; const double PI = acos(-1); template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;} template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;} template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;} template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;} LL l, r; int a[N]; LL f[N]; LL getVal(int l, int r) { LL ans = 0; for(int i = l; i <= r; i++) ans *= 2, ans += a[i]; return ans; } LL solve(LL x) { if(x <= 1) return 0; int tot = 0; for(LL i = x; i; i /= 2) a[tot++] = i % 2; reverse(a, a + tot); vector<int> fac; vector<LL> way; LL ans = 0; for(int i = 2; i < tot; i++) { fac.clear(); way.clear(); for(int j = 1; j < i; j++) { if(i % j) continue; fac.push_back(j); } way.resize(SZ(fac)); for(int j = 0; j < SZ(way); j++) way[j] = 1LL << (fac[j] - 1); for(int j = 0; j < SZ(way); j++) { ans += way[j]; for(int k = j + 1; k < SZ(way); k++) { if(fac[k] % fac[j] == 0) way[k] -= way[j]; } } } fac.clear(); way.clear(); for(int i = 1; i < tot; i++) { if(tot % i == 0) fac.push_back(i); } way.resize(SZ(fac)); for(int j = 0; j < SZ(way); j++) { LL val = getVal(0, fac[j] - 1); way[j] = max(val - (1ll << (fac[j] - 1)), 0ll); bool flag = true; for(int k = fac[j]; k + fac[j] - 1 < tot; k += fac[j]) { LL tmp = getVal(k, k + fac[j] - 1); if(tmp > val) break; if(tmp < val) { flag = false; break; } } way[j] += flag; } for(int j = 0; j < SZ(way); j++) { ans += way[j]; for(int k = j + 1; k < SZ(way); k++) { if(fac[k] % fac[j] == 0) way[k] -= way[j]; } } return ans; } int main() { scanf("%lld%lld", &l, &r); printf("%lld", solve(r) - solve(l - 1)); return 0; } /* */