uoj578 校验码

没错,这是道字符串题
\(q(n,c)\to q(n)\)
考虑到一个\(i\)\(q(i)\),将它拆成\(d^2\times t\),其中t的质因子没有完全平方数,也就是\(\mu^2(t)=1\)
则有\(q(i)=d^cq(t)=d^c\)
只考虑一维前缀和的话:
\(\sum\limits_{i=1}^{n}q(i)=\sum\limits_{t=1}^{n}\mu^2(t)\sum\limits_{d^2t\leq n}d^c\)
\(S_1(n)=\sum\limits_{i=1}^{n}i^c\)
则原式化成\(\sum\limits_{t=1}^{n}\mu^2(t)S_1(\lfloor\sqrt{n/t}\rfloor)\)
又有\(\sum\limits_{i=1}^{n}\mu^2(t)=\sum\limits_{i=1}^{\sqrt{n}}\mu(i)\lfloor n/i^2\rfloor\)
那么可以整除分块。
然后扩展到两维:

\[\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}q(ij) \]

\[=\sum\limits_{t_1=1}^{n}\mu^2(t_1)\sum\limits_{t_1d_1^2\leq n}\sum\limits_{t_2}^{m}\mu^2(t_2)\sum\limits_{t_2d_2^2\leq m}d_1^cd_2^cq(t_1t_2) \]

\[=\sum\limits_{t_1=1}^{n}\mu^2(t_1)S_1(\lfloor\sqrt{n/t_1}\rfloor)\sum\limits_{t_2=1}^{m}\mu^2(t_2)S_1(\lfloor\sqrt{m/t_2}\rfloor)\gcd(t_1,t_2)^c \]

\(f(i)\)表示\(\mu*id_c(i)\)则有:

\[=\sum\limits_{t_1=1}^{n}\mu^2(t_1)S_1(\lfloor\sqrt{n/t_1}\rfloor)\sum\limits_{t_2=1}^{m}\mu^2(t_2)S_1(\lfloor\sqrt{m/t_2}\rfloor)\sum\limits_{r|t_1,r|t_2}f(r) \]

\[=\sum\limits_{r}f(r)\sum\limits_{t_1=1}^{\lfloor \frac{n}{r}\rfloor}\mu^2(t_1r)S_1(\lfloor \sqrt{n/(t_1r)}\rfloor)\sum\limits_{t_2=1}^{\lfloor \frac{m}{r}\rfloor}\mu^2(t_2r)S_1(\lfloor \sqrt{m/(t_2r)}\rfloor) \]

再设\(S_2(n,d)=\sum\limits_{i=1}^{n}\mu^2(id)S_1(\lfloor \sqrt{n/i}\rfloor)\)
那么问题就变成了

\[=\sum\limits_{r\leq n}f(r)S_2(\lfloor \frac{n}{r}\rfloor,r)S_2(\lfloor \frac{m}{r}\rfloor,r) \]

考虑如何求这个式子。首先f可以暴力线性筛求解。那么考虑\(S_2\)如何求。
设定一个边界\(L\),将\(\mu^2\)预处理到\(L\)剩下的整除分块。其中\(L=M^{0.6}\)达到最优复杂度。
先处理\(d=1\)\(L\)
\(S_2(n,1)-S_2(n-1,1)=\sum\limits_{i=1}^{n}\mu^2(i)(S_1(\lfloor \sqrt{n/i}\rfloor)-S_2(\lfloor \sqrt{(n-1)/i}\rfloor))\)
其中\(S_1(\lfloor \sqrt{n/i}\rfloor)-S_2(\lfloor \sqrt{(n-1)/i}\rfloor)\not=0\)当且仅当\(i|n\)并且\(n/i\)是完全平方数并且如果差只会差一个值,那么可以枚举完全平方数进行一个差分。
剩下的进行整除分块
\(d>1\)时候递推:

\[S_2(n,k) \]

\[=\sum\limits_{i=1}^{n}\mu^2(ik)S_1(\lfloor\frac{n}{i}\rfloor) \]

\[=\mu^2(k)\sum\limits_{i=1}^{n}[(i,k)=1]\mu^2(i)S_1(\lfloor\frac{n}{i}\rfloor) \]

\[=\mu^2(k)\sum\limits_{d|k}\sum\limits_{i=1}^{\lfloor \frac{n}{d}\rfloor}\mu^2(id)S_1(\lfloor\frac{n}{id}\rfloor) \]

\[=\mu^2(k)\sum\limits_{d|k}\mu(d)S_2(\lfloor\frac{n}{d}\rfloor,d) \]

对于\(S_2(n,d)\)\(nd<=N\)的预处理。
然后还能注意到\(S_2\)中的\(k\leq n\),那么可以暴力拆解质因子了.

纸上谈兵没有卵用,滚去写代码了.

O3虽好,可不要贪杯哦

#pragma GCC optimize(3)
#include<vector>
#include<bits/extc++.h>
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;typedef unsigned int uint;
	#define pf printf
	#define F(i,a,b) for(int i=a;i<=b;i++)
	#define D(i,a,b) for(int i=a;i>=b;i--)
	inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=5e5+10,LL=5e6;
	int n,c,sq,L,mv[LL],prime[LL],co;ll m;uint f[LL],S1[LL],pw[LL],mu[LL],mu2[LL];std::vector<uint>S2[N];
	__gnu_pbds::gp_hash_table<ll,uint>mp2;bool vis[LL];
	inline void init(){
		S2[1].clear();S2[1].resize(max(n,L)+2);
		F(i,2,n){S2[i].clear();S2[i].resize(n/i+2);}
	}
	inline uint ksm(uint a,int b){uint ans=1;while(b){if(b&1)ans*=a;a*=a;b>>=1;}return ans;}
	inline void initmu(int n){
		mu[1]=mu2[1]=1;
		F(i,2,n){
			if(!vis[i])prime[++co]=i,mu[i]=-1,mv[i]=i;
			F(j,1,co){
				if(prime[j]*i>n)break;
				vis[prime[j]*i]=1;
				mv[i*prime[j]]=prime[j];
				if(i%prime[j]==0)break;
				mu[i*prime[j]]=-mu[i];
			}
		}
		F(i,1,n)mu2[i]=mu[i]*mu[i];
		F(i,1,n)mu2[i]+=mu2[i-1];
		F(i,1,n)mu[i]+=mu[i-1];
	}
	inline void initprime(int n){F(i,1,n)pw[i]=ksm(i,c);}
	inline void initS1(int n){F(i,1,n)S1[i]=S1[i-1]+pw[i];}
	inline void initf(int n){
		memset(f,0,sizeof(uint)*(n+1));
		F(i,1,n){const int Mu=mu[i]-mu[i-1];const int lim=n/i;F(j,1,lim)f[i*j]+=Mu*pw[j];}
	}
	inline void initS2(int n){
		int sq=sqrt(n),sql=sqrt(L);
		if(L>n){
			F(d,1,sql){
				const int lim=L/d/d;
				for(int i=1;i<=lim;i++)S2[1][i*d*d]+=(mu2[i]-mu2[i-1])*pw[d];
			}
			F(i,1,L)S2[1][i]+=S2[1][i-1];
		}else{
			F(d,1,sq){
				const int lim=n/d/d;
				for(int i=1;i<=lim;i++)S2[1][i*d*d]+=(mu2[i]-mu2[i-1])*pw[d];
			}
			F(i,1,n)S2[1][i]+=S2[1][i-1];
		}
		F(d,1,sq){
			const int lim=n/d/d;
			for(int i=1;i<=lim;i++){
				const int lim2=lim/i;
				for(int k=2;k<=lim2;k++)
					S2[k][i*d*d]+=(mu2[i*k]-mu2[i*k-1])*pw[d];
			}
		}
		F(i,2,n){
			const int lim=n/i;
			for(int j=1;j<=lim;j++)S2[i][j]+=S2[i][j-1];
		}
	}
	inline uint getmu2(ll n){
		if(n<=L)return mu2[n];
		if(mp2.find(n)!=mp2.end())return mp2[n];
		uint ans=0;
		for(int l=1,r;l<=n/l;l=r+1){
			r=sqrt(n/(n/l/l));
			ans+=(mu[r]-mu[l-1])*(n/l/l);
		}return mp2[n]=ans;
	}
	inline void part(int x,std::vector<int> &d){
		d.push_back(1);
		while(x>1){
			const int v=mv[x];
			const int nsiz=d.size();
			for(int i=0;i<nsiz;i++)d.push_back(d[i]*v);
			x/=v;
		}
	}
	std::vector<int>dw;
	inline uint getS2(ll n,int k){
		if(!n)return 0;
		if(n*k<=EMT::n)return S2[k][n];
		uint ans=0;
		if(k==1){
			if(n<=L)return S2[1][n];
			for(ll l=1,r;l<=n;l=r+1){
				const ll v=sqrt(n/l);r=n/v/v;
				ans+=(getmu2(r)-getmu2(l-1))*S1[(int)sqrt(n/l)];
			}
		}else{
			if(mu2[k]==mu2[k-1])return 0;
			dw.clear();part(k,dw);
			for(auto d:dw)ans+=(mu[d]-mu[d-1])*getS2(n/d,d);
			ans*=mu2[k]-mu2[k-1];
		}return ans;
	}
	inline short main(){
		int T=read();
		initmu(4500000);
		while(T--){
			n=read(),m=read(),c=read();
			if(n>m)n^=m^=n^=m;
			sq=sqrt(m),L=pow(m,0.6);
			init();
			initprime(max(sq,n));
			initS1(sq);initf(n);initS2(n);
			uint ans=0;
			F(r,1,n)ans+=f[r]*getS2(n/r,r)*getS2(m/r,r);
			pf("%u\n",ans);
		}
		return 0;
	}
}
signed main(){return EMT::main();}

posted @ 2022-04-27 20:12  letitdown  阅读(87)  评论(1编辑  收藏  举报