CF1139D Steps to One
这,暴力写了2h还没写出来,正解写了10min就一遍AC了
话说我没想到 \(1\) 到 \(n\) 中的因数总数是 \(O(n\ln n)\) 级别是不是该被毙掉啊
暴力
首先设个 \(dp_i\) 表示当前 \(\gcd\) 为 \(i\) ,需要 \(dp_i\) 次变成 \(1\)
\(ans=1+\dfrac{\sum_{i=1}^{m}dp_i}{m}\)
前面那个 \(1\) 只要自己打个暴力就很好理解了,因为一开始没有数。
如果你不知道为啥这么设,多试几次就知道这么设有种能往下推的感觉
发现如果连边 \(i\to factor_i\) 是个 \(DAG\) ,那么模拟建反图从 \(1\) 往上转移可得 \(dp_i=1+\dfrac{\sum_{j=1}^{m}dp[\gcd(i,j)]}{m}\)
然后我决定写个暴力验证一下,然后一调就是2h。因为右边也有 \(dp_i\) ,所以要把右边 \(\dfrac{m}{i}\) 个 \(dp_i\) 移过来。
这就是暴力唯一的价值
正解
既然都要移过来了,那还不如推正解。
带回去:
然后把那几个 \(dp_i\) 提出来移过去
维护 \(f_T=\sum_{d|T}dp[d]*\mu(\dfrac{T}{d})\)
发现只要先更新 \(dp\) 再更新 \(f\) 就可以避开 \(d<i\) 这个奇怪的东西了
考虑如何快速更新 \(f\) ,我们发现只要枚举 \(i|T\) ,修改所有 \(T\) 那么均摊下来总复杂度是 \(\sum_{i=1}^{n}\dfrac{n}{i}=n\ln n\)
然后就是我傻逼的地方了,总因数个数也是 \(O(n\ln n)\) 级别的,直接预处理出来即可
复杂度 \(O(n\ln n)\)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef double db;
#define mkp(x,y) make_pair(x,y)
#define fi first
#define se second
#define pb(x) push_back(x)
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=0;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f?x:-x;
}
#define N 100005
#define mod 1000000007
int qpow(int n,int k){int res=1;for(;k;k>>=1,n=1ll*n*n%mod)if(k&1)res=1ll*res*n%mod;return res;}
void fmod(int&x){x+=x>>31&mod,x-=mod,x+=x>>31&mod;}
int m,mu[N],pri[N],cnt,f[N],dp[N],inv[N],ans;
bool vis[N];
vector<int>d[N];
void Sieve(const int&K){
mu[1]=1;
for(int i=2;i<=K;++i){
if(!vis[i])mu[i]=-1,pri[++cnt]=i;
for(int j=1;i*pri[j]<=K;++j){
vis[i*pri[j]]=1;
if(i%pri[j]==0){mu[i*pri[j]]=0;break;}
mu[i*pri[j]]=-mu[i];
}
}
for(int i=1;i<=K;++i)
for(int j=1;i*j<=K;++j)
d[i*j].pb(i);
inv[1]=1;
for(int i=2;i<=K;++i)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
}
signed main(){
cin>>m,Sieve(m);
dp[1]=0;
for(int i=2;i<=m;++i){
int res=m;
for(int j:d[i])
fmod(res+=1ll*(m/j)*f[j]%mod);
dp[i]=1ll*res*inv[m-m/i]%mod;
for(int j=1;i*j<=m;++j)
fmod(f[i*j]+=dp[i]*mu[j]);
}
ans=m;
for(int i=1;i<=m;++i)fmod(ans+=dp[i]);
printf("%lld\n",1ll*ans*inv[m]%mod);
return 0;
}
\(\color{black}{\texttt{F}}\color{red}{\texttt{orever_Pursuit}}\) 10min就秒了这题,还是 \(O(n)\) 的,我被吊打了/ll