• Codeforces 215E Periodical Numbers 容斥原理


    Periodical Numbers

    我们先按长度分类对于当前处理的长度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;
    }
    
    /*
    */
  • 相关阅读:
    我的20130220日 在北京 do{ Web Develop } while(!die)
    关于NVelocity模板引擎初学总结
    C# 23种设计模式汇总
    基于模型的设备故障检测
    图像去噪之光斑去除
    虹膜识别
    封闭曲线拟合
    基于故障树的系统可靠性分析
    图像识别之棋子识别
    时间序列的模式距离
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10833575.html
Copyright © 2020-2023  润新知