BSOJ5019&P6156&P6222 简单题

题目

求:

\[\large \sum_{i=1}^n\sum_{j=1}^m(i+j)^k\mu^2(\gcd(i,j))\gcd(i,j) \]

\(\large T = 10^4,1 \leq K < 2^{31},n,m\le 10^7\)

题目:

P6222 「P6156 简单题」加强版

P6156 简单题

BSOJ5019【Digimon】3 primary color(三原色)

分析

先推一下柿子:

\[\large \begin{split} &\ \ \ \ \ \sum_{i=1}^n\sum_{j=1}^m(i+j)^k\mu^2(\gcd(i,j))\gcd(i,j)\\ &=\sum_{d=1}^nd^{k+1}\mu^2(d)\sum_{i=1}^{\lfloor\frac nd\rfloor}\sum_{j=1}^{\lfloor\frac md\rfloor}(i+j)^k[(i,j)=1]\\ &=\sum_{d=1}^{n}\mu^2(d)d^{k+1}\sum_{t=1}^{\lfloor\frac nd\rfloor}\mu(t)t^k\sum_{i=1}^{\lfloor\frac n{td}\rfloor}\sum_{j=1}^{\lfloor\frac m{td}\rfloor} (i+j)^k \end{split} \]

然后设 \(\large S(n,m)=\sum\limits_{i=1}^n\sum\limits_{j=1}^m(i+j)^k\)

发现剩下的柿子还是一个二次除法分块,于是考虑传统艺能,直接枚举倍数把第二个除法分块变成卷积的形式:

\(T=td\)

\[\large \sum_{T=1}^{n}T^kS(\lfloor\frac nT\rfloor,\lfloor\frac mT\rfloor)\sum_{d\vert T}d\mu^2(d)\mu(\frac Td) \]

接下来考虑两个问题。

首先是如何预处理 \(S(n,m)\)

如果我们考虑枚举 \((i+j)\) 的和,设 \(\large F(n)=\sum\limits_{i=1}^ni^k\)

\[\large S(n,m)=\sum\limits_{i=m+1}^{n+m}\sum\limits_{j=1}^ij^k-\sum\limits_{i=1}^{n}\sum\limits_{j=1}^i=\sum\limits_{i=m+1}^{n+m}F(i)-\sum\limits_{i=1}^{n}F(i)=\sum_{i=1}^{n+m}F(i)-\sum\limits_{i=1}^{n}F(i)-\sum\limits_{i=1}^{m}F(i) \]

那么设 \(\large G(n)=\sum\limits_{i=1}^nF(i)\) ,有 \(\large S(n,m)=G(n+m)-G(n)-G(m)\)

于是我们直接线性筛每一个数的 \(k\) 次幂,然后做二阶前缀和即可得到 \(G\)

第二个问题是处理 \(\large \sum\limits_{d\vert T}d\mu^2(d)\mu(\frac Td)\)

发现是 \(id*\mu^2*\mu\) ,根据狄利克雷卷积的性质,得到这也是个积性函数,设为 \(f\)

讨论一下线性筛需要的端点值之后,直接线性筛预处理即可。

最后柿子就是一个除法分块,直接做。

代码

#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
	x=0;bool f=false;char ch=getchar();
	while(!isdigit(ch)){f|=ch=='-';ch=getchar();}
	while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
	x=f?-x:x;
	return ;
}
template <typename T>
inline void write(T x){
	if(x<0) x=-x,putchar('-');
	if(x>9) write(x/10);
	putchar(x%10^48);
	return ;
}
#define ll long long
#define ull unsigned long long
#define rep(i,x,y) for(int i=(x);i<=(y);i++)
#define dep(i,y,x) for(int i=(y);i>=(x);i--)
const int N=2e7+5,M=2e5+5;
int n,m,prime[N],cnt;
unsigned int k;
unsigned int f[N],pre[N],Pow[N],Ans;
bitset<N>vis;
inline unsigned int QuickPow(unsigned int x,unsigned int y){
	unsigned int res=1;
	while(y){
		if(y&1) res=res*x;
		x=x*x;
		y>>=1;
	} 
	return res;
}
inline void GetPrimes(int d){
	vis[1]=true;f[1]=pre[1]=Pow[1]=1;//对1进行定义 
	for(int i=2;i<=d;i++){
		if(!vis[i]) prime[++cnt]=i,f[i]=(unsigned int)(i-1),Pow[i]=QuickPow((unsigned int)i,k);//对质数进行定义 
		pre[i]=pre[i-1]+f[i]*Pow[i];
		for(int j=1;j<=cnt&&i*prime[j]<=d;j++){
			vis[i*prime[j]]=true;
			Pow[i*prime[j]]=Pow[i]*Pow[prime[j]];
			if(i%prime[j]==0){
				int tmp=i/prime[j];
                if(tmp%prime[j]) f[i*prime[j]]=f[tmp]*(unsigned int)(-prime[j]);//对质数的若干次幂进行定义(一般由f[i]递推);
                break;
            }
			f[i*prime[j]]=f[i]*f[prime[j]];//通过 f(n),f(m) 计算 f(nm) 
		}
	}
	for(int i=2;i<=d;i++) Pow[i]+=Pow[i-1];
	for(int i=2;i<=d;i++) Pow[i]+=Pow[i-1];
	return ;
}
inline unsigned int GetSum(int x){return Pow[x+x]-(Pow[x]+Pow[x]);}
signed main(){
	int t;read(t);read(n),read(k);GetPrimes(n*2);
	while(t--){
		read(n);Ans=0;
		for(int l=1,r;l<=n;l=r+1){
			r=n/(n/l);	
			Ans+=GetSum((n/l))*(pre[r]-pre[l-1]);
		}
		write(Ans);putchar('\n');
	}
	return 0;
}
posted @ 2021-09-05 10:31  __Anchor  阅读(30)  评论(0编辑  收藏  举报