P6222 「P6156 简单题」加强版

P6222 「P6156 简单题」加强版

\(T\) 组询问。一开始给定一个常数 \(m\)。每次询问单独给定 \(n\)。请你求出:

\(\sum_{i=1}^{n}\sum_{j=1}^{n} (i+j)^m \gcd(i,j) \mu^2(\gcd(i,j)) \pmod {2^{32}}\)
枚举k=(i,j)

\(\displaystyle \sum_{k}k\mu^{2}(k)\sum_{i=1}^{n/k}\sum_{j=1}^{n/k}(ik+jk)^m[(i,j)=1]\)

经典莫反
\(=\displaystyle \sum_{k}k\mu^{2}(k)\sum_{i=1}^{n/k}\sum_{j=1}^{n/k}(ik+jk)^m \sum_{d|i,d|j}\mu(d)\)
\(=\displaystyle \sum_{k}k\mu^{2}(k) \sum_{d}\sum_{i=1}^{n/kd}\sum_{j=1}^{n/kd}(ikd+jkd)^m\)

\(=\displaystyle \sum_{T}T^m\sum_{k|T}k\mu^2(k)\mu({\frac{T}{k}})\sum_{i=1}^{n/T}\sum_{j=1}^{n/T}(i+j)^m\)

\(S(n)=\displaystyle \sum_{i=1}^{n}\sum_{j=1}^{n}(i+j)^m\)
将表格写出来之后
发现\(S(n)-S(n-1)\)是两段连续的数的k次方和。
所以我们只用求k次方和即可,而这个东西其实也是可以筛的。

对于
\(g(T)=\displaystyle\sum_{k|T}k\mu^2(k)\mu({\frac{T}{k}})\)
明显g是积性函数
考虑质因子\(p^c\)的贡献

  • c=1,贡献为p-1
  • c=2,贡献为-p
  • \(c >2\) ,贡献为0

那么直接线筛即可。

#include<bits/stdc++.h>
#define fo(i,a,b) for (uint (i)=(a);(i)<=(b);(i)++)
#define fd(i,b,a) for (ll (i)=(b);(i)>=(a);(i)--)
#define eb emplace_back
#define pi pair<ll,ll>
#define mk(x,y) make_pair((x),(y))
#define lc (o<<1)
#define rc ((o<<1)|1)
//#define A puts("Yes")
//#define B puts("No")
#define fi first
#define se second
using namespace std;
typedef unsigned int uint;
typedef double db;
const int N=2e7+5;
const int M=1e6+5;
uint z[N],s[N];
long long g[N/2];
uint p[M],tot,n,m,f[N];
int cnt[N];
bool vis[N];
uint power(uint a,uint b){
	uint t=1,y=a;
	while (b) {
		if (b&1) t=t*y;
		y=y*y;
		b/=2;
	}
	return t;
}
int main() {
//    freopen("data.in", "r", stdin);
//    freopen("data.out", "w", stdout);

	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	int T;
	cin>>T>>n>>m;
	fo(i,2,n*2) {
		if (!vis[i]) {
			p[++tot]=i;
			z[i]=power(i,m);
		}
		fo(j,1,tot) {
			if (i*p[j]>=N) break;
			vis[i*p[j]]=1;
			z[i*p[j]]=z[i]*z[p[j]];
			if (i%p[j]==0) break;	
		}
	}
	
	fo(i,2,n) {
		if (!vis[i]) {
			cnt[i]=1;
			g[i]=i-1;
		}
		fo(j,1,tot) {
			if (i*p[j]>n) break;
			if (i%p[j]==0) {
				if (cnt[i]>=2) g[i*p[j]]=0,cnt[i*p[j]]=3;
				else if (cnt[i]==1) {
					cnt[i*p[j]]=2;
					g[i*p[j]]=g[i]/(p[j]-1)*(-p[j]);
				}
				break;	
			}
			g[i*p[j]]=g[i]*(p[j]-1),cnt[i*p[j]]=1;
		}
	}
	
	g[1]=1;
	z[1]=1;
	fo(i,2,n*2) z[i]=z[i]+z[i-1];

	s[1]=power(2,m);
	fo(i,2,n) s[i]=s[i-1]+z[2*i-1]-z[i]+z[2*i]-z[i];
	
	fo(i,1,n) f[i]=f[i-1]+(z[i]-z[i-1])*(uint)g[i];
		
	while (T--) {
		cin>>n;
		uint ans=0;
		for (uint lt=1,rt;lt<=n;lt=rt+1) {
			rt=n/(n/lt);
			ans+=(f[rt]-f[lt-1])*s[n/lt];
		}
		cout<<ans<<"\n";
	}
	
	
    return 0;
    


}

总结:

  • 自然数k次幂也是可以用筛法求的。
  • 对于积性函数,可以讨论每个质因子\(p^c\)的贡献,然后乘起来。
posted @ 2024-08-19 14:57  gan_coder  阅读(26)  评论(0)    收藏  举报