• [BZOJ3560] DZY Loves Math V


    Description

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

    img

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

    Input

    第一行一个正整数n。

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

    Output

    仅一行答案。

    Sample Input

    3
    6
    10
    15
    

    Sample Output

    1595
    

    Solution

    注意到(varphi)是积性函数,那么我们可以对其每一个质因子进行考虑,对于质数(p),设(a_i)(p)的指数为(b_i),那么贡献就是:

    [sum_{i_1=0}^{b_1}sum_{i_2=0}^{b_2}cdotssum_{i_n=0}^{b_n}varphi(p^{sum i}) ]

    化简一下,注意特判(1)

    [egin{align} &((sum_{i_1=0}^{b_1}sum_{i_2=0}^{b_2}cdotssum_{i_n=0}^{b_n}p^{sum i})-1)frac{p-1}{p}+1\ =&((prod_{i=1}^{n}sum_{j=0}^{b_i}p^j)-1)frac{p-1}{p}+1\ =&((prod_{i=1}^{n}frac{p^{b_i+1}-1}{p-1})-1)frac{p-1}{p}+1\ end{align} ]

    然后答案就是:

    [prod_{pin prime}((prod_{i=1}^{n}frac{p^{b_i+1}-1}{p-1})-1)frac{p-1}{p}+1 ]

    枚举质因子暴力算就好了。

    时间复杂度(O(a+nlog a))

    #include<bits/stdc++.h>
    using namespace std;
     
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
     
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    #define lf double
    #define ll long long 
    
    const int maxn = 2e5+10;
    const int maxm = 1e7+10;
    const int inf = 1e9;
    const lf eps = 1e-8;
    const int mod = 1e9+7;
    
    #define vec_iter vector<int > :: iterator 
    
    int qpow(int a,int x) {
    	int res=1;
    	for(;x;x>>=1,a=1ll*a*a%mod) if(x&1) res=1ll*res*a%mod;
    	return res;
    }
    
    int n,a[maxn],vis[maxm],pri[maxm],tot,mx,lst[maxm];
    vector<int > cnt[maxm];
    
    int main() {
    	read(n);for(int i=1;i<=n;i++) read(a[i]),mx=max(mx,a[i]);
    	lst[1]=1;
    	for(int i=2;i<=mx;i++) {
    		if(!vis[i]) pri[++tot]=i,lst[i]=i;
    		for(int j=1;j<=tot&&i*pri[j]<=mx;j++) {
    			vis[i*pri[j]]=1;lst[i*pri[j]]=pri[j];
    			if(i%pri[j]==0) break;
    		}
    	}
    	for(int i=1;i<=n;i++) {
    		int pre=0,c=0;
    		while(a[i]!=1) {
    			if(pre!=0&&pre!=lst[a[i]]) cnt[pre].push_back(c),c=0;
    			pre=lst[a[i]],a[i]/=lst[a[i]],c++;
       		}cnt[pre].push_back(c);
    	}
    	int ans=1;
    	for(int i=1;i<=tot;i++) {
    		int res=1,p=pri[i];
    		if(cnt[p].empty()) continue;
    		for(vec_iter it=cnt[p].begin();it!=cnt[p].end();it++)
    			res=1ll*res*(qpow(p,(*it)+1)-1)%mod*qpow(p-1,mod-2)%mod;
    		res=1ll*(res-1)*(p-1)%mod*qpow(p,mod-2)%mod;
    		ans=1ll*ans*(res+1)%mod;
    	}
    	write(ans);
    	return 0;
    }
    
  • 相关阅读:
    从TCP三次握手说起——浅析TCP协议中的疑难杂症
    动态绑定是如何实现的?
    C++对象的内存模型
    C/C++关键字
    libevent库介绍--事件和数据缓冲
    libevent编程疑难解答
    大型工程多个目录下的Makefile写法
    C++中的RAII机制
    C++中的智能指针
    二叉树的非递归遍历
  • 原文地址:https://www.cnblogs.com/hbyer/p/10588939.html
Copyright © 2020-2023  润新知