首页 > 其他分享 >Codeforces 1630 E Expected Components 题解 (组合数学)

Codeforces 1630 E Expected Components 题解 (组合数学)

时间:2022-12-23 14:33:45浏览次数:70  
标签:1630 cnt 排列 frac 题解 rep Codeforces len MOD

题目链接

首先明确概念:

  • 排列。指的就是一个把数组a重排得到的序列,两个排列相等当且仅当它们对应位全都相等
  • 环形排列。指的是把数组a重排得到的序列首尾相接得到的环形数组,两个环形排列相等当且仅当它们通过位移能够变得对应位全部相等

这题其实是要对所有不同的环形排列,求其中连续相同的数构成的连通块个数的期望值。特判a中数全相同的情况,其余情况其实只要求出相邻两个数不同的位置个数的期望值就行了,把这个期望值称为一个环形排列的"权值"一个排列的权值指的是把它视为环形排列之后的权值(1,n也算相邻)。对于一个排列p,有多少个与它不同的排列在作为循环排列时与它相同?其实这与p的最短循环节长度有关,令这个长度为\(len\)。这里的循环节必须是完整的,也就是\(|p|\ mod \ len=0\),且把\(p\)平均切成\(\frac{|p|}{len}\)段之后每段都相同。观察发现对于p,有\(len-1\)个与它不同的排列在作为循环排列时与它相同,也就是等价类大小为\(len\)。如果能对每个\(len\)求出所有最小循环节大小为\(len\)的不同排列的权值和\(f_{len}\)与总个数\(cnt_{len}\),那么题目要求的答案就是\(\frac xy\),其中\(x=\sum_{len|n}\frac{f_{len}}{len},y=\sum_{len|n}\frac{cnt_{len}}{len}\)。

令\(a\)中数\(i\)出现的次数为\(b_i\)。现在枚举\(len\),尝试计算出\(f_{len}与cnt_{len}\)。令\(B=\frac n{len}\),显然对于任意i,必须满足\(B|b_i\),否则就不存在最短循环节为len的排列。然后想到用容斥,先计算出实际最小循环节长度为\(len\)的约数的排列的权值和与总个数。令\(b'_i=\frac{b_i}B\)。显然总个数为\(\frac{len!}{\prod{b'_i!}}\)。对于权值和,注意到整个排列被分成了\(B\)段,每一段都相等,所以可以把每一段都视为首尾相接的一个环形排列计算权值和,然后乘\(B\)。在每一段构成的小环形排列中,任意相邻两个位置贡献1的概率都相同,因为这个排列是随机的。这个概率的计算方法是先枚举靠前一个位置的值为\(i\),其发生的概率为\(\frac{b'_i}{len}\);后面一个位置的值必须与其不同,概率为\(\frac{len-b'_i}{len-1}\)。枚举所有的i,把这个概率相加即可。先暂时让\(f_{len}=\)此时算出的权值和,\(cnt_{len}=\)此时算出的总个数,然后进行这样一步容斥就能算出真正的\(f和cnt\):

for(int i=1;i<=n;++i) for(int j=i+i;j<=n;j+=i) (f[j]+=MOD-f[i])%=MOD,(cnt[j]+=MOD-cnt[i])%=MOD;

时间复杂度\(O(能过)\)。不知道怎么证明,但是看上去感觉不会被卡。

点击查看代码
#include <bits/stdc++.h>

#define rep(i,n) for(int i=0;i<n;++i)
#define repn(i,n) for(int i=1;i<=n;++i)
#define LL long long
#define pii pair <int,int>
#define fi first
#define se second
#define mpr make_pair
#define pb push_back

void fileio()
{
  #ifdef LGS
  freopen("in.txt","r",stdin);
  freopen("out.txt","w",stdout);
  #endif
}
void termin()
{
  #ifdef LGS
  std::cout<<"\n\nEXECUTION TERMINATED";
  #endif
  exit(0);
}

using namespace std;

const LL MOD=998244353;

LL qpow(LL x,LL a)
{
	LL res=x,ret=1;
	while(a>0)
	{
		if(a&1) (ret*=res)%=MOD;
		a>>=1;
		(res*=res)%=MOD;
	}
	return ret;
}

LL t,n,a[1000010],b[1000010],f[1000010],cnt[1000010],fac[1000010],inv[1000010],rinv[1000010];
vector <LL> v;

void solve(LL len)
{
  LL dv=n/len;
  rep(i,v.size()) v[i]/=dv;

  cnt[len]=fac[len];rep(i,v.size()) (cnt[len]*=inv[v[i]])%=MOD;
  LL possi=0,mul=rinv[len]*rinv[len-1]%MOD;
  rep(i,v.size()) (possi+=v[i]*(len-v[i])%MOD*mul)%=MOD;
  f[len]=possi*n%MOD*cnt[len]%MOD;

  rep(i,v.size()) v[i]*=dv;
}

int main()
{
  fileio();

  fac[0]=1;repn(i,1000005) fac[i]=fac[i-1]*i%MOD;
  rep(i,1000003) inv[i]=qpow(fac[i],MOD-2),rinv[i]=qpow(i,MOD-2);
  cin>>t;
  rep(tn,t)
  {
    scanf("%lld",&n);
    rep(i,n+3) b[i]=f[i]=cnt[i]=0;
    rep(i,n) scanf("%d",&a[i]),++b[a[i]];
    v.clear();
    repn(i,n) if(b[i]) v.pb(b[i]);
    if(v.size()==1)
    {
      puts("1");
      continue;
    }
    repn(len,n) if(n%len==0)
    {
      bool bad=false;
      LL dv=n/len;
      rep(i,v.size()) if(v[i]%dv!=0){bad=true;break;}
      if(bad) continue;
      solve(len);
    }
    //cout<<f[2]<<' '<<cnt[2]<<' '<<f[4]<<' '<<cnt[4]<<endl;
    repn(i,n) for(int j=i+i;j<=n;j+=i) (f[j]+=MOD-f[i])%=MOD,(cnt[j]+=MOD-cnt[i])%=MOD;
    LL up=0,dn=0;
    repn(i,n) if(n%i==0) (up+=f[i]*qpow(i,MOD-2))%=MOD,(dn+=cnt[i]*qpow(i,MOD-2))%=MOD;
    LL ans=up*qpow(dn,MOD-2)%MOD;
    printf("%d\n",ans);
  }

  termin();
}

标签:1630,cnt,排列,frac,题解,rep,Codeforces,len,MOD
From: https://www.cnblogs.com/legendstane/p/codeforces-1630-e-Expected-Components-solution.html

相关文章

  • CF1753B 题解
    \(\mathcalPreface\)题目传送门\(\mathcalSolution\)定理:\(n!\cdot(n+1)=(n+1)!\)这题就是围绕以上定理展开的。如果加入一个数\(a_i\)满足\(\operatornam......
  • Codeforces Global Round 24(B,C)
    CodeforcesGlobalRound24(B,C)这一次vp真是大失所望,我只写了A,第二题最后发现离那个答案很近了,但就是没想到,看来还是功力不到家呀B这道题的大意是有一个数组,我们可......
  • Python从入门到精通(第2版)——pyuic5: error: no such option: -m的问题解决
    前言在学习《Python从入门到精通(第2版)》的第15章GUI界面编程——15.2.4将.ui文件转换为.py文件时,按照书中步骤出错时的问题解决,希望对同样学习本书的同学有所帮助。问......
  • [省选联考 2021 B 卷] 数对 题解
    题目描述给定\(n\)个正整数\(a_i\),请你求出有多少个数对\((i,j)\)满足\(1\lei\len\),\(1\lej\len\),\(i\nej\)且\(a_i\)是\(a_j\)的倍数。提示对于......
  • chrome使用拖拽本地扩展时无法安装的问题解决办法
    在使用Chrome拖拽安装本地扩展时会提示无法安装,可以采用以下两个方法解决1、修改.crx文件文件格式为zip,并进行解压,然后打开扩展安装界面的开发者模式,使用加载已解压的扩展......
  • Codeforces 1654 G Snowy Mountain 题解 (重心分治)
    题目链接假设现在起点已经确定,我们观察从这个起点开始能走的最长路径长什么样。把这条最长路径中所有的非平地路径拿出来,它们肯定连成一线,因为不允许上坡;而一条路径重复走......
  • Codeforces Round #837 (Div. 2)(持续更新)
    Preface补题ing上周由于疫情鸽了好多场,趁现在空下来尽量多写点吧A.HossamandCombinatoricsSB题,直接统计下最大的数和最小的数的个数即可注意所有数相同的情况要特......
  • Educational Codeforces Round 139 D. Lucky Chains
    LuckyChains题面翻译给定两个数·a,b,(a,b给到了1e7)执行如下语句:while(gcd(a,b)==1)a++,b++,cnt++;求出cnt的值。样例#1样例输入#145151337891......
  • luoguP2254 [NOI2005]瑰丽华尔兹 题解
    传送门题意给定\(n\)行\(m\)列的矩阵和钢琴的初始位置\((x,y)\),给定\(k\)个时间段,在每个时间段内钢琴会向给定方向(上/下/左/右)滑动,\(1\)秒移动\(1\)个单位长度......
  • 问题解决1
      出现这样的问题需要导入jar包 ......