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\)
那么可以整除分块。
然后扩展到两维:
设\(f(i)\)表示\(\mu*id_c(i)\)则有:
再设\(S_2(n,d)=\sum\limits_{i=1}^{n}\mu^2(id)S_1(\lfloor \sqrt{n/i}\rfloor)\)
那么问题就变成了
考虑如何求这个式子。首先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,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();}