题解:P10855 【MX-X2-T4】「Cfz Round 4」Gcd with Xor

Link\text{Link}

题意

x=1ni=1xgcd(i,ix)k\sum_{x=1}^n\sum_{i=1}^x\gcd(i,i\oplus x)^k109+710^9+7 取模的结果。

分析

既然 O(nlog2n)O(n\log^2 n) 的做法已经被说烂了,那我就来一个更烂的 O(nlog3n)O(n\log^3n) 的做法。

nn 二进制下的最高位为 tntnn2=2tn+1n2=2^{tn+1}

直接开始推式子,gcdk\gcd^k 显然拆不开,考虑枚举它:

=d=1ndkx=1ni=1x[gcd(i,ix)=d]=\sum_{d=1}^nd^k\sum_{x=1}^n\sum_{i=1}^x[\gcd(i,i\oplus x)=d] =d=1ndk(1+i=1nj=1n2[gcd(i,j)=diijn])=\sum_{d=1}^nd^k(1+\sum_{i=1}^n\sum_{j=1}^{n2}[\gcd(i,j)=d\land i\le i\oplus j\le n])

多出来的 11j=0j=0 的情况。

接着考虑处理条件 iij=xi\le i\oplus j=x,由于 j0j\neq 0,所以 i<xi<x

不放设 iixxt+1tnt+1\sim tn 位均相同,第 tt 位时 it=0,xt=1i_t=0,x_t=1,那么就有 jt=1j_t=1jt+1tn=0j_{t+1\sim tn}=0。也就是说当且仅当 it=0i_t=0ttjj 的最高位时 i<xi<x!于是令 UtU_t 表示 {iit=0in}\{i|i_t=0\land i\le n\}VtV_t 表示 {jjt=12t+1>jjn2}\{j|j_t=1\land 2^{t+1}>j\land j\le n2\},那么答案为:

d=1ndk(1+t=0tniUtjVt[gcd(i,j)=dijn])\sum_{d=1}^nd^k(1+\sum_{t=0}^{tn}\sum_{i\in U_t}\sum_{j\in V_{t}}[\gcd(i,j)=d\land i\oplus j\le n])

f(p)=t=0tniUtpijVtpj[ijn]f(p)=\sum_{t=0}^{tn}\sum_{i\in U_t\land p|i}\sum_{j\in V_{t}\land p|j}[i\oplus j\le n],显然这个东西可以在 Trie\texttt{Trie} 树上预处理出来,均摊后总复杂度为 O(tn2nlogn)O(tn^2 n\log n)

接着对 [gcd(i,j)=d][\gcd(i,j)=d] 进行莫比乌斯反演:

d=1ndk(1+c=1n/dμ(c)f(cd))\sum_{d=1}^nd^k(1+\sum_{c=1}^{n/d}\mu(c) f(cd))

这部分计算的复杂度是 O(nlogn)O(n\log n) 的,总复杂度大概为 O(nlog3n)O(n\log ^3n),看起来十分过不了,然而给出的数的值是连续的,所以其在 U,VU,V 中的分布是均匀的,只要大力卡常就能在单点大约 980ms\texttt{980ms} 内通过。别缩短时限啊qwq

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std; 
ll read(){
	ll x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} 
	return x*f;
}
void write(ll x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+'0');
}
const int N=(1<<18)+10,M=19;
const ll mod=1e9+7;
int T,n,k,Log[N],tn;
ll dk[N],f[N];
ll qmi(ll a,ll b){
	ll ans=1;
	while(b){
		if(b&1)ans=ans*a%mod;
		a=a*a%mod;b>>=1;
	}
	return ans;
}
vector<int>U[M],V[M],sep[N],facu[N],facv[N];
int m,pri[N],vis[N],miu[N];
void init(int n){
	vis[1]=1;miu[1]=1;
	for(int i=2;i<=n;i++){
		if(!vis[i]){
			vis[i]=pri[++m]=i;
			miu[i]=-1;
		}
		for(int j=1;j<=m&&i*pri[j]<=n;j++){
			vis[i*pri[j]]=pri[j];
			miu[i*pri[j]]=miu[i]*-1;
			if(i%pri[j]==0){
				miu[i*pri[j]]=0;break;
			}
		}
	}
}
int find(int d,int x,int l,int r){
	if(facu[d][r]<x)return r+1;
	int mid;
	while(l<r){
		mid=(l+r)>>1;
		if(facu[d][mid]>=x)r=mid;
		else l=mid+1;
	}
	return l;
}
struct Trie{
	int ch[N*20][2],tot=1,p;
	int sz[N*20];
	void change(register int x,int v){
		sz[p=1]+=v;
		for(int i=tn,c;i>=0;i--){
			c=(x>>i)&1;
			if(!ch[p][c])ch[p][c]=++tot;
			p=ch[p][c];
			sz[p]+=v;
		}
	}
	void clear(){
		for(register int i=1;i<=tot;i++)ch[i][0]=ch[i][1]=0;
		tot=1;
	}
	ll ask(int p,int t,int d,int ms,int l,int r){
		if(!p||!sz[p]||l>r)return 0;
		if(t==-1){
			return 1ll*sz[p]*(r-l+1);
		}
		ll ans=0;
		int mpos=find(d,ms|(1<<t),l,r);
		if((n>>t)&1){
			if(l<=mpos-1){
				ans+=1ll*sz[ch[p][0]]*(mpos-l);
				ans+=ask(ch[p][1],t-1,d,ms,l,mpos-1);
			}
			if(mpos<=r){
				ans+=1ll*sz[ch[p][1]]*(r-mpos+1);
				ans+=ask(ch[p][0],t-1,d,ms|(1<<t),mpos,r);
			}
		}
		else{
			ans+=ask(ch[p][0],t-1,d,ms,l,mpos-1);
			ans+=ask(ch[p][1],t-1,d,ms|(1<<t),mpos,r);
		}
		return ans;
	}
}tr;
void solve(){
	tn=Log[n];int n2=(1<<tn+1);
	for(register int t=0;t<=tn;t++){
		U[t].clear();V[t].clear(); 
		for(register int i=1;i<=n;i++){
			if(!((i>>t)&1))
				U[t].push_back(i);
		}
	}
	for(register int i=1,j,tc;i<n2;i++){
		j=i;tc=-1;
		while(j)j>>=1,tc++;
		V[tc].push_back(i);
	}
	for(register int i=1;i<=n;i++){
		dk[i]=qmi(i,k);
		f[i]=0;
	}
	for(register int t=0;t<=tn;t++){
		for(register int i=1;i<=n;i++){
			facu[i].clear();
			facv[i].clear();
		}
		for(register auto x:U[t]){
			for(register auto p:sep[x])
				facu[p].push_back(x);
		}
		for(register auto x:V[t]){
			for(register auto p:sep[x])
				facv[p].push_back(x);
		}
		for(register int d=1;d<=n;d++){
			for(register auto x:facv[d])
				tr.change(x,1);
			f[d]=(f[d]+tr.ask(1,tn,d,0,0,facu[d].size()-1))%mod;
			for(register auto x:facv[d])
				tr.change(x,-1);
		}
	}
	ll ans=0,res;
	for(register int d=1;d<=n;d++){
		res=1;
		for(register int c=1;c<=n/d;c++)
			res+=miu[c]*f[c*d];
		ans=(ans+dk[d]*res%mod);
	}
	ans=(ans%mod+mod)%mod;
	write(ans);putchar('\n');
}
int main(){
	T=read();
	Log[0]=-1;
	for(register int i=1;i<N;i++)Log[i]=Log[i>>1]+1;
	for(register int i=1;i<N;i++){
		for(register int j=1;j*j<=i;j++){
			if(i%j==0){
				sep[i].push_back(j);
				if(j*j!=i)
					sep[i].push_back(i/j);
			}
		}
	}
	init(N-5);
	while(T--){
		tr.clear();
		n=read();k=read();
		solve();
	}
	return 0;
}
posted @ 2024-08-21 13:42  luckydrawbox  阅读(7)  评论(0)    收藏  举报  来源