zoukankan      html  css  js  c++  java
  • CF396E On Iteration of One Well-Known Function [欧拉函数 III]

    On Iteration of One WellKnown FunctionOn Iteration of One Well-Known Function


    Descriptionmathcal{Description}
    给出 n=i=1mpiain=prodlimits_{i=1}^mp_i^{a_i}, 求 φ(φ(...φ(n)))φ(φ(...φ(n))) .

    m105,pi106,ai1017,k1018.mle10^5, p_ile10^6, a_i le 10^{17}, k le 10^{18} .


    正解部分
    因为 φ(n)=ni=1mpi1pivarphi(n)=nprodlimits_{i=1}^mdfrac{p_i-1}{p_i},
    所以对一个整数 xx 进行一次 φvarphi 操作即

    • 乘一次 i=1m1piprodlimits_{i=1}^{m}frac{1}{p_i}, 即pip_i项的幂数减 11 .
    • 乘一次 i=1m(pi1)prodlimits_{i=1}^{m}(p_i-1), 对 pi1p_i-1 分解质因数, 使得对应的较小的质数的幂数增加若干.

    那么怎么快速地去求解本题的式子呢?

    从小到大共有10610^6个质数, 对每个质数单独处理,
    设当前质数为 pip_i, 还需进行 leftileft_iφvarphi 操作, 指数为 aia_i,

    为保证效率最大化, 将 pip_i 进行 t=min(ai,lefti)t=min(a_i, left_i)φvarphi 操作,
    这样会使得 (pi1)t(p_i-1)^t 分解, “散落” 到比pip_i 更小的质数中,
    所以需要循环往复地对每个质数进行这个操作, 直到没有任何质数有操作的余地 .


    对当前 pip_i, 若进行了 ttphiphi 操作, 则需要在指数为 00 时, SOSi=t1SOS_i = t-1 次操作不去减 leftileft_i, 因为可能还有指数不为 00 的希望,
    过了 SOSiSOS_i 后若指数仍然为 00, 表示没救了, 需要使 leftileft_i 减小 .


    实现部分
    在质数筛时记录每个数 xx 的最小质因子 come[x]come[x], 分解质因数时, 就可以利用 come[x]come[x] 直接分解 .

    记得在开始时每个质数的 leftleft 都为 KK, 因为每个质数都有可能参与运算 .

    #include<cstdio>
    #include<algorithm>
    #define reg register
    typedef long long ll;
    
    const int maxn = 1e6+5;
    
    int M;
    int p_cnt;
    int p[maxn];
    int q[maxn];
    int Mp[maxn];
    int come[maxn];
    
    ll K;
    ll a[maxn];
    ll SOS[maxn];
    ll left[maxn];
    
    void Sieve(){
            for(reg int i = 2; i < maxn; i ++){
                    if(!come[i]) come[i] = i, p[++ p_cnt] = i, Mp[i] = p_cnt;
                    for(reg int j = 1; j <= p_cnt && i*p[j] < maxn; j ++){
                            int t = i*p[j];
                            come[t] = p[j];
                            if(i % p[j] == 0) break ;
                    }
            }
    }
    
    int main(){
            //freopen("a.out", "w", stdout);
            Sieve();
            scanf("%d", &M);
            for(reg int i = 1; i <= M; i ++){
                    scanf("%d", &q[i]);
                    scanf("%I64d", &a[Mp[q[i]]]);
            }
            scanf("%I64d", &K);
            for(reg int i = 1; i <= p_cnt; i ++) left[i] = K;
            bool flag = 1;
            while(flag){
                    flag = 0;
                    for(reg int i = 1; i <= p_cnt; i ++)
                            if(a[i]){ 
                                    if(!left[i]) continue ;
                                    ll t = std::min(a[i], left[i]);
                                    a[i] -= t, left[i] -= t;
                                    SOS[i] += t-1, flag = 1;
                                    int tmp = p[i]-1;
                                    while(tmp != 1){
                                            int id = Mp[come[tmp]];
                                            a[id] += t;
                                            tmp /= come[tmp];
                                    }
                            }else if(SOS[i]) SOS[i] --;
                            else if(left[i])left[i] --;
            }
            int Ans = 0;
            for(reg int i = 1; i <= p_cnt; i ++) if(a[i]) Ans ++;
            printf("%d
    ", Ans);
            for(reg int i = 1; i <= p_cnt; i ++)
                    if(a[i]) printf("%d %I64d
    ", p[i], a[i]);
            return 0;
    }
    
    
  • 相关阅读:
    tp3.2和tp5的区别
    tp(调试模式,空操作,跨控制器调用,跨方法跳转--redirect(),框架语法,创建model模型)
    tp 连表查 分页 模糊查询
    thinkphp if和eq的区别
    js 面向对象例子
    JS字符串转换为JSON的四种方法笔记
    json在php中的使用之如何转换json为数组
    window.frames用法
    php js 数组排序
    控件常用
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822559.html
Copyright © 2011-2022 走看看