[bzoj3944] Sum

Description

img

Input

一共T+1行

第1行为数据组数T(T<=10)

第2~T+1行每行一个非负整数N,代表一组询问

Output

一共T行,每行两个用空格分隔的数ans1,ans2

Sample Input

6
1
2
8
13
30
2333

Sample Output

1 1
2 0
22 -2
58 -3
278 -3
1655470 2

solution

杜教筛模板题无敌卡常题

先搬出套路式子:

[S(n)=sum_{i=1}^{n}(f*g)(i)-sum_{i=2}^{n}g(i)S(lfloorfrac{n}{i} floor) ]

对于(mu(n)),拿一个(I(n)=1)和他卷起来,可以得到:

[S(n)=1-sum_{i=2}^{n}S(lfloorfrac{n}{i} floor) ]

对于(varphi(n)),同样拿一个(I(n))卷起来,得到:

[S(n)=frac{n*(n+1)}{2}-sum_{i=2}^{n}S(lfloorfrac{n}{i} floor) ]

然后飞速的敲完代码,提交,(TLE)......

可能是我太弱了,所有的卡常技巧都用上了,然而并没有什么用....

然后突然发现一个这样的事情:

对于(varphi(n)),其实可以写成这个样子:

[varphi(n)=sum_{i=1}^{n}epsilon(gcd(i,n)) ]

其中(epsilon(n)=[n=1])

然后苦思冥想无果后闲着无聊对前缀和反演下:

[egin{align} S(n)&=sum_{i=1}^{n}sum_{d=1}^iepsilon(gcd(d,i))\ &=sum_{i=1}^{n}sum_{d=1}^isum_{d_1|i&d_1|d}mu(d_1)\ &=sum_{i=1}^{n}sum_{d_1|i}sum_{d=1}^{frac{i}{d_1}}mu(d_1)\ &=sum_{i=1}^nsum_{d_1|i}mu(d_1)frac{i}{d_1}\ &=sum_{d_1=1}^nsum_{i=1}^{frac{n}{d_1}}mu(d_1)*i\ &=sum_{d_1=1}^nmu(d_1)*frac{lfloorfrac{n}{d_1} floor(lfloorfrac{n}{d_1} floor+1)}{2} end{align} ]

然后惊奇的发现,这里面用到的(mu(n))的前缀和正好是第二问要求的,然后这么一来直接快了一倍不止,成功的只跑了(6sAC)

#include<bits/stdc++.h>
using namespace std;

#define ll long long 

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) x=-x,putchar('-');
	if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('
');}

const int maxn = 3e6+1;

int pri[maxn],vis[maxn],n,tot,inv2,inv6,mu[maxn];

void sieve() {
	mu[1]=1;
	for(int i=2;i<maxn;i++) {
		if(!vis[i]) pri[++tot]=i,mu[i]=-1;
		for(int t,j=1;j<=tot&&i*pri[j]<maxn;j++) {
			vis[t=i*pri[j]]=1;
			if(!(i%pri[j])) {mu[t]=0;break;}
			mu[t]=-mu[i];
		}
	}
	//for(int i=1;i<maxn;i++) phi[i]=phi[i-1]+phi[i];
	for(int i=1;i<maxn;i++) mu[i]=mu[i-1]+mu[i];
}

map<int,int > Mu;

/*ll sum_phi(int n) {
	if(n<maxn) return phi[n];
	if(Phi[n]) return Phi[n];
	ll T=2,res=1ll*n*(n+1)/2;
	while(T<=n) {
		ll pre=T;T=n/(n/T);
		res=res-1ll*(T-pre+1)*sum_phi(n/T);T++;
	}
	return Phi[n]=res;
	}*/

ll sum_mu(ll n) {
	if(n<maxn) return mu[n];
	if(Mu[n]) return Mu[n];
	ll T=2,res=1;
	while(T<=n) {
		ll pre=T;T=n/(n/T);
		res=res-1ll*(T-pre+1)*sum_mu(n/T);T++;
	}
	return Mu[n]=res;
}

ll sum_phi(ll n) {
	ll T=1,ans=0;
	while(T<=n) {
		ll pre=T;T=n/(n/T);
		ans+=1ll*(n/pre)*(n/pre+1)/2*(1ll*sum_mu(T)-1ll*sum_mu(pre-1));
		//printf("%lld %lld
",1ll*sum_mu(T)-1ll*sum_mu(pre-1));
		T++;
	}
	return ans;
}

signed main() {
	int t,n;read(t);sieve();
	while(t--) read(n),printf("%lld %lld
",sum_phi(n),sum_mu(n));
	//cerr << (double) clock()/1e6 << endl;
}

原文地址:https://www.cnblogs.com/hbyer/p/10073676.html