#C241111D. 集合操作


#C241111D. 集合操作

标签(Label)

  • 期望
  • 数学

网址(Website)

题目详情 - 集合操作 - Super

题解 - 集合操作 - Super

题目(Problem)

题解(Solution)

$\qquad$只打了 $\text{60pts}$ ,和今天的 $E$ 题一样,类似的想法,输出 $\sum_{i=1}^{i\le n}\frac{1}{dep_i}$ 。

出题者题解

算法分析

【对于60分的做法】

请参考CF280C:

考虑对问题做如下转化:随机一个排列 $P$,第 $i$ 次操作删除 $P_i$ 的倍数,但如果 $P_i$ 已经被删除则不计入次数。

由期望线性性,答案是每个 $P_i$ 被记入次数的概率之和。也就是 $P_i$ 与其因子们,$P_i$ 是在排列里第一个出现的概率,也就是 $\frac{1}{d_{P_i}}$,其中 $d_u$ 是 $u$ 的因子个数。

令 $f(x) = \frac{1}{d_x}$,容易发现 $f(x)$ 是积性函数,可以线性筛,获得部分分。

【对于100分的做法】

可以使用 min25/洲阁筛 实现。

总之选取你喜欢的筛子,可以得到 $O(n^{1-\epsilon})$ 或 $O(\frac{n^{\frac{3}{4}} }{\log n})$ 之类的复杂度。

代码(Code)

#include<bits/stdc++.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#define For(i,l,r) for(int i=l;i<=r;i++)
#define Rof(i,l,r) for(int i=l;i>=r;i++)
using namespace std;
#define P pair<int,int> 
#define int long long
#define x first
#define y second
inline int rd(){
	char c;bool f=false;while(!isdigit(c=getchar()))f=c=='-';int x=c^48;
	while(isdigit(c=getchar())){x=(((x<<2)+x)<<1)+(c^48);}return f?-x:x;
}const int inf = 0x3f3f3f3f3f3f3f3f;
const int N = 1012345;
bool ST;
double Tim;

int n,ans,mod,dep[N];
inline void add(int &x,int y){if((x+=y)>=mod)x-=mod;}
inline void mul(int &x,int y){x=x*y%mod;}
inline int ksm(int x,int k){
	int res=1;while(k){
		if(k&1) mul(res,x);
		mul(x,x),k>>=1;
	}return res;
}

void Solve(){
	n=rd(),mod=rd();
	For(i,1,n) for(int j=i;j<=n;j+=i) dep[j]++;
	For(i,1,n) add(ans, ksm(dep[i],mod-2));
	printf("%lld\n",ans);
}

bool ED;
signed main(){
	cerr<<abs(&ST-&ED)/1024./1024.<<"MB\n";
	freopen("set.in","r",stdin);
	freopen("set.out","w",stdout);
	int Tt=1;Tim=clock();
	while(Tt--) Solve();
	return cerr<<"TIME:"<<(clock()-Tim)/CLOCKS_PER_SEC,0;
}

文章作者: WolfDeer
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 WolfDeer !
  目录