2021牛客多校第四场H H-Convolution_2021牛客暑期多校训练营4 (nowcoder.com)

题意:

\(p_i为第i个质数,x=\prod_i p_i^{a_i},y=\prod_i p_i^{b_i}\)

定义\(x\bigotimes y=\prod_i p_i^{|a_i-b_i|}\)

现定义\(b_i=\sum\limits_{1\le j,k\le n,j\bigotimes k=i}a_jk^c\)

求出所有的\(b_i\)

范围\(1\le n\le 10^6,0\le a_i<998244353,0\le c\le 10^9\)

思路:

首先要搞清楚\(\bigotimes\)这个运算的本质

相当于把 \(x\)\(y\) 分解质因数后除去它们相同的因子

\(x\bigotimes y=\frac{lcm(x,y)}{gcd(x,y)}=\frac{xy}{gcd(x,y)^2}\)

\(b_i=\sum\limits_{1\le j,k\le n,j\bigotimes k=i}a_jk^c=\sum\limits_{1\le j,k\le n,\frac{jk}{gcd(j,k)^2}=i}a_jk^c=\sum\limits_{j=1}^n\sum\limits_{k=1}^n[\frac{jk}{gcd(j,k)^2}=i]a_jk^c\)

\(x'=\frac{j}{gcd(j,k)},y'=\frac{k}{gcd(j,k)}\)

考虑枚举\(gcd(i,k)=d\),那么\(j=x'd,k=y'd\)

那么\(b_i=\sum\limits_{x'|i}\sum\limits_{d=1}^{min(\frac{i}{x'},\frac{i}{y'})}a_{x'd}{(y'd)}^c\)

继续分式子,令\(f_{x,m}=\sum\limits_{d=1}^{m}a_{xd}d^c\)

#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
const int maxn=1e6+50;
int ksm(int a,int b)
{
	int res=1;
	while(b)
	{
		if(b&1)res=1ll*res*a%mod;
		a=1ll*a*a%mod;
		b>>=1;
	}
	return res;
}
int gcd(int a,int b)
{
	if(b==0)return a;
	else return gcd(b,a%b);
}
int a[maxn],p[maxn],ans[maxn];
int main()
{
	int n,c;
	scanf("%d%d",&n,&c);
	for(int i=1;i<=n;i++)
	scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
	p[i]=ksm(i,c);
	for(int i=1;i<=n;i++)
	{
		vector<int>f(n/i+1);
		for(int j=1;i*j<=n;j++)
		{
			f[j]=(1ll*f[j-1]+1ll*a[i*j]*p[j]%mod)%mod;
		}
		for(int j=1;i*j<=n;j++)
		{
			if(gcd(i,j)==1)
			{
				int m=min(n/i,n/j);
				ans[i*j]=(1ll*ans[i*j]+1ll*f[m]*p[j]%mod)%mod;
			}
		}
	}
	int sum=0;
//	for(int i=1;i<=n;i++)
//	cout<<ans[i]<<" ";
	for(int i=1;i<=n;i++)
	sum^=ans[i];
	printf("%d\n",sum);
	return 0;
}