• SCUT


    https://scut.online/p/11

    T了好多次,还想用mutimap暴力分解每个数的质因数。后来记录每个数的最小质因子过了。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int n, m, MOD;
    
    const int SIZE = 1e6, SIZEP = 8e4;
    
    int p2[SIZE + 5], p5[SIZE + 5];
    int p[SIZEP + 5], ptop;
    int minp[SIZE + 5];
    
    void init() {
        for(int i = 2; i <= SIZE; i *= 2) {
            for(int j = i; j <= SIZE; j += i)
                p2[j] ++;
        }
        for(int i = 5; i <= SIZE; i *= 5) {
            for(int j = i; j <= SIZE; j += i)
                p5[j] ++;
        }
        minp[1] = 1;
        for(int i = 2; i <= SIZE; i++) {
            if(!minp[i]) {
                p[++ptop] = i;
                minp[i] = ptop;
            }
            for(int j = 1, t; j <= ptop && (t = i * p[j]) <= SIZE; j++) {
                minp[t] = j;
                if(i % p[j] == 0)
                    break;
            }
        }
        //cout<<ptop<<endl;
    }
    
    
    int cntp[SIZEP + 5];
    
    void cnt(int n, int d) {
        while(n != 1) {
            cntp[minp[n]] += d;
            n /= p[minp[n]];
        }
    }
    
    int qpow(ll x, int n) {
        ll res = 1;
        while(n) {
            if(n & 1)
                res = res * x % MOD;
            x = x * x % MOD;
            n >>= 1;
        }
        return res;
    }
    
    int calc() {
        memset(cntp, 0, sizeof(cntp));
        m = min(n - m, m);
        for(int i = 1; i <= m; ++i) {
            cnt(n - i + 1, 1);
            cnt(i, -1);
        }
        int min10 = min(cntp[1], cntp[3]);
        cntp[1] -= min10, cntp[3] -= min10;
        printf("%d ", min10);
        ll ans = 1;
        for(int i = 1; i <= ptop; ++i)
            ans = ans * (qpow(p[i], cntp[i])) % MOD;
        return ans % MOD;
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        init();
        while(~scanf("%d%d%d", &n, &m, &MOD))
            printf("%d
    ", calc());
    }
    

    事实上,这个是个阶乘(DQ的方法),那么阶乘以内的各个质因子的贡献是可以算出来的,具体而言,2会贡献n/2个2,4再贡献n/4个2,8再贡献n/8个2。

    用上面的方法,每个质因数会贡献一个log,一共是80000logn,而我的方法则是1000000logn,而且我对p2和p5的预处理并不是线性的(后面发现这两个白处理)。

    二分memset,丧心病狂。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int n, m, MOD;
    
    const int SIZE = 1e6, SIZEP = 8e4;
    int p[SIZEP + 5], ptop;
    int minp[SIZE + 5];
    
    void init() {
        minp[1] = 1;
        for(int i = 2; i <= SIZE; i++) {
            if(!minp[i]) {
                p[++ptop] = i;
                minp[i] = ptop;
            }
            for(int j = 1, t; j <= ptop && (t = i * p[j]) <= SIZE; j++) {
                minp[t] = j;
                if(i % p[j] == 0)
                    break;
            }
        }
        //cout<<ptop<<endl;
    }
    
    int maxptop;
    int cntp[SIZEP + 5];
    
    void cnt(int n, int d) {
        /*while(n != 1) {
            cntp[minp[n]] += d;
            n /= p[minp[n]];
        }*/
        for(int i=1;i<=maxptop;++i){
            int tmp=n;
            while(tmp/=p[i]){
                cntp[i]+=tmp*d;
            }
        }
    }
    
    int qpow(ll x, int n) {
        ll res = 1;
        while(n) {
            if(n & 1)
                res = res * x % MOD;
            x = x * x % MOD;
            n >>= 1;
        }
        return res;
    }
    
    int calc() {
        maxptop=min(int(lower_bound(p+1,p+1+ptop,n)-p),ptop);
        memset(cntp, 0, sizeof(cntp[0])*(maxptop+1));
        /*m = min(n - m, m);
        for(int i = 1; i <= m; ++i) {
            cnt(n - i + 1, 1);
            cnt(i, -1);
        }*/
        cnt(n,1);
        cnt(m,-1);
        cnt(n-m,-1);
        int min10 = min(cntp[1], cntp[3]);
        cntp[1] -= min10, cntp[3] -= min10;
        printf("%d ", min10);
        ll ans = 1;
        for(int i = 1; i <= maxptop; ++i){
            if(cntp[i])
                ans = ans * (qpow(p[i], cntp[i])) % MOD;
        }
        return ans % MOD;
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        init();
        while(~scanf("%d%d%d", &n, &m, &MOD))
            printf("%d
    ", calc());
    }
    
  • 相关阅读:
    【转载】Android应用框架及常用工具类总结
    【Android】Android开发规范的一点小体会
    【Android】解决Android的ListView控件滚动时背景变黑
    【Android】侧边栏SlidingMenu
    【Android】解决RadioButton+FragmentPagerAdapter+Fragment切换页面数据加载的问题
    【Android】ListView动态视图显示不全
    Android编码规范
    【Android】两个日期相差几天和两个日期比较大小
    Linux基础之快照克隆、Xshell优化、Linux历史
    Android APP打包时,出错:"XXX" is not translated in "af" (Afrikaans), "am" (Amharic)
  • 原文地址:https://www.cnblogs.com/Yinku/p/11297087.html
Copyright © 2020-2023  润新知