51nod1847 奇怪的数学题

题目大意

\[\sum _i^N\sum_j^Nsgcd(i,j)^k \]

\(N \le 1e9 ,k \le 50\)

先推式子:

\(x\)的最大不等于x的约数是\(f(x)​\)

\[\begin{aligned} &\sum _i^N\sum_j^Nsgcd(i,j)^k \\ =&\sum _d^N \sum _i^{\lfloor\frac nd\rfloor}\sum_j^{\lfloor\frac nd\rfloor} [gcd(i,j)=1]f(d)^k \\ =&\sum _d^N (2\sum _i^{\lfloor\frac nd\rfloor}\varphi(i) -1) * f(d)^k \end{aligned} \]

前面可以杜教筛,现在关注如何求\(\sum f(d)^k\)

考虑min25筛,min25筛容斥的一步正好求的是最小质因子是\(prime_i\)的一堆值。将这一步减去的全部加到答案上,就行了。具体如下

\[g(i,0)=\sum _{i=2}^N i^k \\ g(i,j)=g(i,j-1)-(g(\lfloor\frac i {prime_j}\rfloor,j-1)-\sum _{p=1}^{j-1}prime_p^k)*(prime_j^k) \\ h(i)+=(g(\lfloor\frac i {prime_j}\rfloor,j-1)-\sum _{p=1}^{j-1}prime_p^k) \]

需要注意的是\(\sum _{i=2}^N i^k\)怎么求:

\[\begin{aligned} &\sum _i^n i^k \\ =&\sum _i^n \sum _{j=0}^k \begin{Bmatrix} k \\ j \end{Bmatrix}i^\underline{j} \\ =&\sum _{j=0}^k \begin{Bmatrix} k \\ j \end{Bmatrix} \sum _i^n i^\underline{j} \\ =&\sum _{j=0}^k \begin{Bmatrix} k \\ j \end{Bmatrix} \frac {(n+1)^\underline{j+1}} {j+1} \end{aligned} \]

代码

#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
typedef long long ll;
typedef unsigned int uint;
const int N=1e6+5;
int n,prime[N],pcnt,v[N],phi[N],k;
uint pre[N],preprime[N];

inline void sieve(int n=1000000){
	phi[1]=1;
	for(int i=2;i<=n;i++){
		if(!v[i])prime[++pcnt]=i,phi[i]=i-1;
		for(int j=1;j<=pcnt&&1ll*prime[j]*i<=n;j++){
			int nxt=i*prime[j];v[nxt]=1;
			if(i%prime[j]) phi[nxt]=phi[i]*(prime[j]-1);
			else {
				phi[nxt]=phi[i]*prime[j];
				break;
			}
		}
	}
	for(int i=1;i<=n;i++)pre[i]=pre[i-1]+phi[i];
}
gp_hash_table<int,uint> Table;
uint calc(int x){
	if(x&1)return (uint)x*((x+1)>>1);
	else return (uint)(x>>1)*(x+1);
}
uint PHI(int n){
	if(n<=1000000)return pre[n];
	if(Table.find(n)!=Table.end())return Table[n];
	uint ans=calc(n);
	for(int u=2,v;u<=n;u=v+1){
		v=n/(n/u);
		ans-=(uint)(v-u+1)*PHI(n/u);
	}
	return Table[n]=ans;
}
uint S[100][100];
inline void stir_init(int n=60){
	S[0][0]=1;
	for(int i=1;i<=n;i++)for(int j=1;j<=i;j++){
		S[i][j]=S[i-1][j-1]+(uint)j*S[i-1][j];
	}
}

inline uint qs(int n,int m=k){
	uint ans=0;
	for(int j=0;j<=m;j++){
		uint cur=1;bool flag=0;
		for(int k=0;k<=j;k++){
			if(!flag && (n+1-k)%(j+1)==0)flag=1,cur*=(uint)((n+1-k)/(j+1));
			else cur*=(uint)(n+1-k);
		}
		ans+=cur*S[m][j];
	}
	return ans;
}

int Sqr;
int id1[N],id2[N],w[N],m;
uint f[N],g[N],Count[N];

uint qpow(uint a,int b){uint ret=1;for(;b;b>>=1,a=a*a)if(b&1)ret=ret*a;return ret;}

inline void init(){
	Sqr=sqrt(n);
	for(int u=1,v;u<=n;u=v+1){
		v=n/(n/u);
		w[++m]=n/u;
		if(w[m]<=Sqr)id1[w[m]]=m;
		else id2[n/w[m]]=m;
		f[m]=qs(n/u)-1;
		Count[m]=n/u-1;
	}
	for(int j=1;1ll*prime[j]*prime[j]<=n;j++){
		uint Pw=qpow(prime[j],k);preprime[j]=preprime[j-1]+Pw;
		for(int i=1;i<=m && 1ll*prime[j]*prime[j] <= w[i];i++){
			int idd=(w[i]/prime[j])<=Sqr?id1[w[i]/prime[j]]:id2[n/(w[i]/prime[j])];
			f[i]-=Pw*(f[idd]-preprime[j-1]);
			g[i]+=f[idd]-preprime[j-1];
			Count[i]-=(Count[idd]-j+1);
		}
	}
}
int getid(int x){
	if(x==0)return 0;
	return x<=Sqr?id1[x]:id2[n/x];
}

int main()
{
	sieve();stir_init();
	cin >> n >> k;
	init();
	uint ans=0;
	for(int u=1,v;u<=n;u=v+1){
		v=n/(n/u);
		
		int id=getid(v),pst=getid(u-1);
		ans+=((g[id]+Count[id]) - (g[pst]+Count[pst]))*((uint)2*PHI(n/u)-1);
	}
	cout << ans << endl;
}
posted @ 2019-06-19 11:18  jerome_wei  阅读(309)  评论(0编辑  收藏  举报