zoukankan      html  css  js  c++  java
  • bzoj DZY Loves Math V

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 509  Solved: 284
    [Submit][Status][Discuss]

    Description

    给定n个正整数a1,a2,…,an,求

     

    的值(答案模10^9+7)。

    Input

    第一行一个正整数n。
    接下来n行,每行一个正整数,分别为a1,a2,…,an。

    Output

    仅一行答案。

    Sample Input

    3
    6
    10
    15

    Sample Output

    1595

    HINT



    1<=n<=10^5,1<=ai<=10^7。共3组数据。

    Source

     
    还是喜欢数论题hhhh,至少不用想那么久。。。。
    首先φ是积性函数,这就提示我们可以质因数分解。
    我们只要把这个函数在每个质因子下的答案算出来然后都乘起来就行了。
    于是现在的问题就变成了当a[1],a[2],,,,a[n]在质数p上的次数分别为 b[1],b[2],,,,b[n]时我们如何求出答案。
     
    我一开始想了个比较zz的做法,暴力大背包,,,,dp[i]表示指数和为i的有多少种方法凑到,然后这个质因子的答案
    就是1+dp[1]*(p-1)+dp[2]*p*(p-1).......
     
    虽然我毒奶一口随机数据的话这个肯定是能过的,,,,然而出题人不可能这么良心的。。。。
    一旦有某个质因子在所有数中出现的次数和很大很大那么我这个算法就gg了。。。
     
    只能另寻方法。。。
     
    最初始的计算某个质因子下答案的式子是:ans=∑φ(p^(c[1]+c[2]+...c[n]))   ,其中0<=c[i]<=b[i]。
    然后发现这个也是可以像分解质因数一样合成括号的。
    上式=1+ [(p-1)/p]*(π(1+p+p^2+,,,+p^b[i])-1)
     
    注意只有当x==0时p^x不用乘(p-1)/p得到φ(p^x)。
     
    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 100005
    #define maxm 10000000
    #define ha 1000000007
    #define pb push_back
    using namespace std;
    vector<int> g[maxn*20];
    //g[i]存第i个出现的质因子的指数集合 
    int cnt=0,n,m,dy[maxm+5];
    int ans=1,now,mx[maxn*20];
    int mul[maxn];
    
    inline int ksm(int x,int y){
        int an=1;
        for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha;
        return an;
    }
    
    inline void dvd(){
        //质因数分解预处理出每个质因子有的指数集合 
        //dy[i]表示i这个质因子是第几个出现的 
        m=sqrt(now+0.5);
        int c;
        for(int i=2;i<=m;i++) if(!(now%i)){
            c=0;
            if(!dy[i]) dy[i]=++cnt;
            while(!(now%i)) c++,now/=i;
            g[dy[i]].pb(c),mx[dy[i]]=max(mx[dy[i]],c);
            
            if(now==1) break;
        }
        
        if(now!=1){
            if(!dy[now]) dy[now]=++cnt;
            g[dy[now]].pb(1),mx[dy[now]]=max(mx[dy[now]],1);
        }
    }
    
    inline void solve(int x){
        int tot=1,dig=1,pos=dy[x];
        mul[0]=1;
        //预处理等比数列前缀和 
        for(int i=1;i<=mx[pos];i++){
            dig=dig*(ll)x%ha;
            mul[i]=mul[i-1]+dig;
            if(mul[i]>=ha) mul[i]-=ha;
        }
        
        for(int i=g[pos].size()-1;i>=0;i--){
            tot=tot*(ll)mul[g[pos][i]]%ha;
        }
        tot--;
        if(tot<0) tot+=ha;
        tot=tot*(ll)(x-1)%ha*(ll)ksm(x,ha-2)%ha;
        tot++;
        
        ans=ans*(ll)tot%ha;
    }
    
    int main(){
    //    freopen("data.in","r",stdin);
    //    freopen("data.out","w",stdout);
        
        scanf("%d",&n);
        while(n--){
            scanf("%d",&now);
            dvd();
        }
        
        for(int i=2;i<=maxm;i++) if(dy[i]) solve(i);
        
        printf("%d
    ",ans);
        return 0;
    }
     
     
  • 相关阅读:
    asp.net mvc 中使用async/await异步编程
    简述C#中浅复制和深复制
    Angular:自定义表单控件
    Angular:Reactive Form的使用方法和自定义验证器
    Angular:ViewProviders和Providers的区别
    Angular:OnPush变化检测策略介绍
    Angular:利用内容投射向组件输入ngForOf模板
    在Angular中利用trackBy来提升性能
    Angular @HostBinding()和@HostListener()用法
    Angular利用@ViewChild在父组件执行子组件的方法
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8398356.html
Copyright © 2011-2022 走看看