Project Euler 728 题解
Problem 728 Circle of Coins
得到 Wallbreaker5th 的指导。
\(F\) 就是求这些环上区间(记为 \(A\))的异或线性基大小。令 \(A'_i\gets A_i\oplus A_{i+1}\)。现在求 \(\lang A'\rang\) 的线性基。如果可能从全黑和全白间转换,那么 \(\dim \lang A'\rang=\lang A\rang-1\),否则不 \(-1\)。这个转换的条件是 \(\frac k{(n,k)}\equiv 1 \pmod 2\)。
接下来观察到 \(A'_i,A'_{i+k\bmod n},A'_{i+2k\bmod n}\dots\) 覆盖到的集合对于不同等价类(\(i,i+k\dots\) 在一个等价类)无交。因此这些是独立的。
对于一个等价类去掉无法覆盖到的位置,等价类就形如 \(110000,011000,001100,\dots 100001\),有 \(\frac n{(n,k)}\) 个向量。线性基的大小是:\(\frac n{(n,k)}-1\),这是显然的。所以得到:
尝试计算答案。
所以可以直接卷积 \(O(n\log n)\) 解决。应该是可以 \(O(n\log\log n)\) 的,未知线性行不行。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=1e7+5,mod=1e9+7;
int pw[maxn],ipw[maxn],mu[maxn],n,F[maxn],G[maxn],H[maxn],inv[maxn];
bool isp[maxn];vector<int> pr;
int qp(int a,int b){
if(b==0)return 1;
int T=qp(a,b>>1);T=T*T%mod;
if(b&1)T=T*a%mod;
return T;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;mu[1]=1;
for(int i=2;i<=n;i++){
if(!isp[i])mu[i]=-1,pr.push_back(i);
for(auto u:pr){
if(i*u>n)break;
isp[i*u]=1;
if(i%u==0){
mu[i*u]=0;
break;
}
mu[i*u]=-mu[i];
}
}
pw[0]=1;pw[1]=2;ipw[0]=1,ipw[1]=(mod+1)/2;
for(int i=2;i<=n;i++)pw[i]=pw[i-1]*2%mod,ipw[i]=ipw[i-1]*ipw[1]%mod;
for(int i=1;i<=n;i++)inv[i]=qp(i,mod-2);
for(int i=1;i<=n;i++)for(int j=i;j<=n;j+=i)(F[j]+=ipw[i]*mu[j/i])%=mod;
for(int i=1;i<=n;i++)G[i]=i;
for(int i=1;i<=n;i++)for(int j=i;j<=n;j+=i)(H[j]+=G[i]*F[j/i])%=mod;
int ans=0;for(int i=1;i<=n;i++)(ans+=pw[i]*H[i])%=mod;
for(int i=1;i<=n;i++)F[i]=0,H[i]=0;
for(int i=1;i<=n;i++)for(int j=i;j<=n;j+=i)(F[j]+=ipw[i]*mu[j/i]*((j/i)&1))%=mod;
for(int i=1;i<=n;i++)G[i]=(i+1)/2;
for(int i=1;i<=n;i++)for(int j=i;j<=n;j+=i)(H[j]+=G[i]*F[j/i])%=mod;
for(int i=1;i<=n;i++)(ans+=pw[i]*H[i])%=mod;
ans=(ans%mod+mod)%mod;
cout<<ans<<endl;
return 0;
}