bzoj3560 DZY Loves Math V 数论

       由于φ函数的积性,我们可以统计每一个质数p的答案,然后再累乘起来。

       对于质数p,我们求出ai中质因数p的次数bi,那么答案为:

bzoj3560 DZY Loves Math V 数论_第1张图片

       最后将每一次的答案乘起来就好了。

AC代码如下(为什么我前面还有一个0msT_T):

#include<iostream>
#include<cstdio>
#include<algorithm>
#define mod 1000000007
#define ll long long
using namespace std;

int n,cnt,c[3505],sum[105]; bool vis[2505];
struct node{ int x,y; }a[800005];
bool cmp(node aa,node bb){ return aa.x<bb.x || aa.x==bb.x && aa.y<bb.y; }
void dps(int x){
	int i;
	for (i=1; c[i]*c[i]<=x; i++) if (!(x%c[i])){
		a[++cnt].x=c[i]; a[cnt].y=0;
		while (!(x%c[i])){ x/=c[i]; a[cnt].y++; }
	}
	if (x>1){ a[++cnt].x=x; a[cnt].y=1; }
}
void pfs(){
	int i,j;
	for (i=2; i<=3500; i++){
		if (!vis[i]) c[++c[0]]=i;
		for (j=1; j<=c[0] && i*c[j]<=3500; j++){
			vis[i*c[j]]=1;
			if (!(i%c[j])) break;
		}
	}
}
int ksm(int x,int y){
	int t=1; for (; y; y>>=1,x=(ll)x*x%mod) if (y&1) t=(ll)t*x%mod; return t;
}
int main(){
	scanf("%d",&n); int i; pfs();
	for (i=1; i<=n; i++){
		int x; scanf("%d",&x); dps(x);
	}
	sort(a+1,a+cnt+1,cmp);
	int ans=1,j,k,p;
	for (i=1; i<=cnt; i=j+1){
		for (j=i; a[j+1].x==a[i].x && j<cnt; j++);
		p=a[i].x; sum[0]=1;
		for (k=1; k<=a[j].y; k++)
			sum[k]=(ll)sum[k-1]*p%mod;
		for (k=1; k<=a[j].y; k++)
			sum[k]=(sum[k-1]+sum[k])%mod;
		int tmp=1;
		for (k=i; k<=j; k++) tmp=(ll)tmp*sum[a[k].y]%mod;
		tmp=(ll)(tmp-1)*(p-1)%mod*ksm(p,mod-2)%mod+1;
		ans=(ll)ans*tmp%mod;
	}
	printf("%d\n",ans);
	return 0;
}


by lych

2016.2.23

你可能感兴趣的:(数论,欧拉函数,因式分解,线性筛,积性函数)