首页 > 其他分享 >CF698F Coprime Permutation 题解

CF698F Coprime Permutation 题解

时间:2023-04-11 23:24:50浏览次数:50  
标签:CF698F frac 题解 1000002 sqrt 因子 Coprime cnt2

题意

给定一个未填满的数组 \(p\),求有多少种 \(1\sim n\) 的排列 \(p\) 满足对于任意 \(i<j\),都有 \([\gcd(i, j)=1]=[\gcd(p_i, p_j)=1]\),答案对 \(10^9+7\) 取模。

题解

部分参考这篇题解(感觉这篇题解应该是目前为止最详细的吧)。

记 \(P\) 为 \([1,n]\) 中所有素数与 \(1\) 构成的集合,\(g_n\) 为所有在 \(n\) 中出现过的质因子的乘积(\(g_1=1\))。

由于 \(P\) 中任意两数 \(i,j\) 互质,故 \((p_i,p_j)=1\),从而 \((g_{p_i},g_{p_j})=1\)。

因此,记 \(G=\{g_{p_i}|i\in P\}\),根据 \([1,n]\) 中质因子的个数可分析出 \(G\) 是 \(P\) 的一个排列。

进一步对于合数 \(x\),\(g_x=\prod_{i\in P,\gcd(i,x)>1}g_i\) \((1)\)。

因此,如果 \(P\) 中数对应的 \(p\) 值确定了,那么所有数的 \(g\) 值也就都确定了。

先考虑所有 \(p_i\) 都为 \(0\) 的情况。定义 \(S_i=\{it|1\le it\le n,t\in Z\}\),那么 \(|S_i|=\lfloor\frac{n}{i}\rfloor\),于是对于质数 \(i,j\),\(p_i=j\) 的一个条件为 \(|S_i|=|S_j|\)(\(\lfloor\frac{n}{i}\rfloor=\lfloor\frac{n}{j}\rfloor\)),同时可知 \(i\ne j\) 时 \(i,j\gt\sqrt n\) \((2)\)。

确定完所有数的 \(g\) 值后,如果对于 \(i,j\) 有 \(g_{i}=g_{j}\),那么 \(i,j\) 是等价的,于是 \(i,j\) 在 \(p\) 中的位置可以任意交换。

根据上述推导,可以发现如果设 \(cnt_i\) 表示有多少个质数 \(p\) 满足 \(\lfloor\frac{n}{p}\rfloor=i\),\(cnt2_i\) 表示有多少个数的 \(g\) 值等于 \(i\),那么答案即为 \(\prod_{i=1}^n(cnt_i)!(cnt2_i)!\)。

如果位置 \(i\) 的 \(p_i\) 有值,首先要判断该位置上填的值是否合法。设 \(t_{i}\) 为 \(g_i\) 中不超过 \(\sqrt n\) 的质因子的乘积,则 \(\frac{g_i}{t_i}\) 等于 \(g_i\) 的大于 \(\sqrt n\) 的质因子或 \(1\)(没有大于 \(\sqrt n\) 的质因子),不合法的情况有以下三种:

  1. \(t_{i}\ne t_{p_i}\)。注意由 \((2)\) 可以推出对于所有不超过 \(\sqrt n\) 的质数 \(p\),\(g_p=p\),所以 \(g_i\) 和 \(g_{p_i}\) 不超过 \(\sqrt n\) 的质因子应该相同。

  2. \(|S_{\frac{g_i}{t_i}}|\ne|S_{\frac{g_{p_i}}{t_{p_i}}}|\)。因为可以推出 \(g_i\) 的不同质因子个数和 \(g_{p_i}\) 的不同质因子个数相同,并且大于 \(\sqrt n\) 的质因子至多只有一个,所以要么 \(g_i\) 和 \(g_{p_i}\) 同时没有大于 \(\sqrt n\) 的质因子,要么同时有大于 \(\sqrt n\) 的质因子、且根据 \((1)(2)\) 可知 \(|S_{\frac{g_i}{t_i}}|=|S_{\frac{g_{p_i}}{t_{p_i}}}|\)。

  3. \(P,G\) 无法构成一一映射,即存在不同的 \(i,j\in P\) 使得 \(\left[\frac{g_i}{t_i}=\frac{g_j}{t_j}\right]xor\left[\frac{g_{p_i}}{t_{p_i}}=\frac{g_{p_j}}{t_{p_j}}\right]=1\)。前者为 \(1\) 后者为 \(0\) 是说 \(g\) 中存在某个位置 \(g_k\)(其中 \(k\gt\sqrt n\),\(k\in P\)),\(g_k\) 要等于 \(2\) 个不同的值;前者为 \(0\) 后者为 \(1\) 是说 \(g\) 中存在某两个位置 \(g_k,g_l\)(其中 \(k,l\gt\sqrt n\),\(k,l\in P\)),\(g_k,g_l\) 要等于 \(1\) 个相同的值。

如果合法,只需修改对应位置的 \(cnt\) 和 \(cnt2\) 的值即可。注意最后一步中 \(i=1\) 或 \(p_i=1\) 时要做一些特判,但大体思路相同。总时间复杂度 \(O(n)\)。

Code

#include<bits/stdc++.h>
#define LL long long
#define mod 1000000007
using namespace std;
int n,p_t=0;
LL ans=1;
int a[1000002],p[1000002],t[1000002],t1[1000002],cnt[1000002],cnt2[1000002],to[1000002];
LL fac[1000002];
bool u[1000002];
inline void init()
{
	for(int i=fac[0]=cnt2[1]=1;i<=n;++i)t[i]=t1[i]=1,fac[i]=(fac[i-1]*i)%mod;
	t[1]=n;
	for(int i=2;i<=n;++i)
	{
		if(!u[i])
		{
			++cnt2[n/(p[++p_t]=i)];
			for(int j=i;j<=n;j+=i)t[j]*=i;
			if(i<=n/i)for(int j=i;j<=n;j+=i)t1[j]*=i;
		}
		for(int j=1;p[j]*i<=n;++j)
		{
			u[p[j]*i]=1;
			if(!(i%p[j]))break;
		}
	}
	for(int i=2;i<=n;++i)++cnt[t[i]];
}
int main()
{
	scanf("%d",&n),init();
	for(int i=1,x;i<=n;++i)
	{
		scanf("%d",&a[i]);
		if(a[i])
		{
			x=t[a[i]]/t1[a[i]];
			if((t1[a[i]]^t1[i]) || ((n/x)^(n/(t[i]/t1[i]))))return 0&puts("0");
			if(a[i]>1)--cnt[t[a[i]]];
			if(a[i]==1)--cnt2[1];
			else if(x>n/x)
			{
				if(!to[x])to[x]=t[i]/t1[i],--cnt2[n/x];
				else if(to[x]^(t[i]/t1[i]))return 0&puts("0");
			}
		}
	}
	for(int i=1;i<=n;++i)(((ans*=fac[cnt[i]])%=mod)*=fac[cnt2[i]])%=mod;
	return 0&printf("%lld",ans);
}

标签:CF698F,frac,题解,1000002,sqrt,因子,Coprime,cnt2
From: https://www.cnblogs.com/18Michael/p/17308243.html

相关文章

  • Codeforces Round 864 (Div. 2) 题解
    A.LiHuaandMaze题目保证了两个点的哈密顿距离至少为\(2\),所以他们不会相邻。只要有点在角上答案就是\(2\),在边上但不在角上就是\(3\),否则就是\(4\)。#include<bits/stdc++.h>#include<ext/pb_ds/assoc_container.hpp>#include<ext/pb_ds/tree_policy.hpp>#includ......
  • 「题解」ABC296Ex Unite
    考虑一行一行往下dp,一个状态需要记录每个格子是否是黑色,对于黑色还有记录其并查集。爆搜跑一下本质不同状态数不是很多,dp就行了。\(m=7\)的时候状态数只有324.#include<cstdio>#include<vector>#include<queue>#include<cstring>#include<iostream>#include<algorithm>......
  • CF1525F 题解
    题意有一个\(n\)个点的DAG,现在有\(k\)波进攻,第\(i\)波有\(i\)个人,它们每个人会选择一条DAG上的路径,并占领这个路径上的所有点,路径之间是不能相交的。第\(i\)波进攻前可以做一些准备,可以花\(1\)秒关闭某个点的所有入边,或关闭某个点的所有出边。第\(i\)波进攻有个......
  • COMP326问题解答
    COMP326Assignment2(15%ofthefinalmark)Due18thApril2023Pleasesubmityoursolutionselectronically(inPDFformat)onCanvasPleasebeawareoftheUniversityguidelinesonplagiarismandcollusion.Themarksforlatesubmissionswillbeaffectedin......
  • ubuntu因为升级自动更新内核而重启无法进入图形界面问题解决
    ubuntu因为升级自动更新内核而重启无法进入图形界面问题解决。我使用的ubuntu版本是22.04LTS。经常因为系统更新软件而自动更新内核,又因为我的PC上安装了NVIDIA的显卡,这个卡对应的驱动是NVIDIA-Linux-x86_64-525.89.02.run。这个驱动要从官网上下载安装,而ubuntu系统自带的驱动是......
  • 项目现状问题解决方案
    成果清单的实时统计:可以通过使用在线协作平台或者项目管理软件来实现成果清单的实时更新与统计。这些工具可以帮助团队成员在同一个平台上实时记录产出和进度,并且可以通过图表和报表等形式呈现出来,方便团队和领导进行跟踪和管理。问题登记的规范化:可以建立一个问题登记和解决......
  • P9203 时效「月岩笠的诅咒」 题解
    题目传送门题目大意判断每次经过以下操作其一后,\(a\)与\(b\)是否相等:将\(a\)加上\(1\),即\(a\getsa+1\);将\(b\)加上\(1\),即\(b\getsb+1\)。解题思路\(a\)和\(b\)都是每次加\(1\),所以如果它们相等,那它们的小数部分应该是相等的,所以问题就变成了判断\(a\)......
  • CF486D 题解
    题目传送门题目分析不算很难的树形\(\text{dp}\)。令\(dp_i\)表示以\(i\)为根的子树中联通子图的个数。在更新的时候,考虑儿子的联通子图和自己的,则有:\[dp_u=dp_u\times(dp_v+1)\]选根的时候将\(a\)最大的作为根节点。还要注意另外一点,就是当\(a_{fa}=a_{v}\)......
  • 2023第14届蓝桥杯C/C++A组参赛记录+部分题解
    比赛记录早上起得还算早,没吃早餐,我吃早餐会瞌睡,也会变蠢。在门口还没来得及和队里其他同学聊几句就进场了......键盘还是一样的难用,软件有codeblocks和dev,很舒服。今年来参加蓝桥杯的人好多啊......女生也好多。听说今年蓝桥杯有统一的正经培训,不过和我这个被踢出蓝桥杯群的......
  • “科大国创杯”2023 年安徽省青少年信息学科普日活动 简要题解
    老年退役选手感受单调队列力量。初中组没有实现,如果有问题欢迎爆d我。小学组T1grade直接累加即可。不需要按百分比算(也就是别/100),那样可能会出现一些浮点数误差。T2order暴力枚举$t$就可以了T3string答案即为$cnt4+cnt5-cnt20$。注意到对于一个数,我们只关心其个位和十位......