Codeforces 题面传送门 & 洛谷题面传送门

u1s1 感觉这个 D1F 比某道 jxd 作业里的 D1F 质量高多了啊,为啥这场的 D 进了 jxd 作业而这道题没进/yun

首先这题肯定有个结论对吧,那么我们就先尝试猜一下什么样的排列符合条件,也就是先考虑这题 \(a_i\)​​ 全是 \(-1\)​​ 的情况怎么做,那么通过观察可以发现,由于判定两个数是否互质的过程中只需要考虑它们的质因子集合即可,因此可以发现如果两个数包含的质因子集合完全相同,那么它们显然是可以互换的,因此假设第 \(i\)​​ 种质因子集合有 \(c_i\)​​ 个数,对于全 \(-1\)​​ 的情况贡献应乘上 \(\prod c_i!\)​​。没了吗?手玩一下样例发现对于 \(n=5\)​​ 的情况 \(3,5\)​​ 也可以交换,我们不妨来分析一波,对于 \(n=5\)​​ 的情况 \(3,5\)​​ 满足 \(\lfloor\dfrac{5}{3}\rfloor=\lfloor\dfrac{5}{5}\rfloor\)​​,也就是说我们可以将 \(5\)​​ 的倍数与 \(3\)​​ 的倍数整体互换,类似地,对于两个质数 \(p_i,p_j\)​​,如果它们满足 \(\lfloor\dfrac{n}{p_i}\rfloor=\lfloor\dfrac{n}{p_j}\rfloor\)​​,那么我们对于 \(k\in[1,\lfloor\dfrac{n}{p_i}\rfloor]\)​​,将 \(p_i·k\)​​ 出现的位置与 \(p_j·k\)​​ 出现的问题交换,不难证明交换前任意两个位置是否互质的情况相同,因此如果交换前满足条件,交换后也满足条件,因此如果再记 \(C_i\)​ 表示有多少个质数 \(p\)​ 满足 \(\lfloor\dfrac{n}{p}\rfloor=i\)​,那么答案还要再乘上 \(\prod C_i!\)​。这样已经是充要条件了吗?没错,打个表可以发现所有符合要求都符合上述两个条件。

然后我打表只看出了第一个结论,然后第二个结论以为 \(>\dfrac{n}{2}\) 的质数也可视作相同,然后就愉快地 WA 12 了

然后考虑存在一个 \(a_i\) 固定的情况,显然对于这样的情况,我们还要找排列中的数在换来换去的过程中,有没有什么量是不变的,显然我们的操作只可能是交换两个质数,不会改变每个位置的 \(a_i\) 的质因子个数,因此如果 \(a_i\) 质因子个数不等于 \(i\) 质因子个数就直接 \(-1\)。同理交换前后,是不改变 \(n\) 除以对应质因子下取整的值的,因此如果我们发现 \(i\) 与 \(a_i\) 中,\(n\) 除以对应质因子下取整的值不同,那也可以直接 \(-1\)。那还有没有需要 \(-1\) 的情况呢?不难发现如果存在一个质因子已经被钦定要映射到别的质因子上,而在 \(i\) 与 \(a_i\) 中这种映射关系出现了冲突,那么也应是 \(-1\)。这里有一个投机取巧(bushi)的技巧,就是显然能够交换的质因子只可能 \(>\sqrt{n}\),而一个 \(\le n\) 的数中最多只有一个 \(>\sqrt{n}\)​ 的质因子,因此对于这种情况我们只用检验最大的质因子是否满足条件即可。如果不存在上述三种情况那肯定是有解的,不同于 \(a_i\) 全是 \(-1\) 的情况的一点是,如果我们发现 \(a_i\ne 0\),那么我们就找出 \(a_i\) 的质因子集合,然后令对应的 \(c_i\) 减 \(1\),然后如果我们找出了一对质因子的映射关系,就将对应的 \(C_i\) 减 \(1\),然后还是输出 \(\prod c_i!·\prod C_i!\)​ 即可。

时间复杂度 \(\sum\limits_{i=1}^n\omega(i)<\mathcal O(7·n)=\mathcal O(n)\)

const int MAXN=1e6;
const int MOD=1e9+7;
int pr[MAXN/8+5],prcnt=0,mnp[MAXN+5];
bitset<MAXN+5> vis;
void sieve(int n){
for(int i=2;i<=n;i++){
if(!vis[i]) pr[++prcnt]=i,mnp[i]=i;
for(int j=1;j<=prcnt&&pr[j]*i<=n;j++){
vis[pr[j]*i]=1;mnp[pr[j]*i]=pr[j];
if(i%pr[j]==0) break;
}
}
}
int n,a[MAXN+5],fac[MAXN+5],mul[MAXN+5],num[MAXN+5];
int to1[MAXN+5],to2[MAXN+5];
int c1[MAXN+5],c2[MAXN+5];
vector<int> pf[MAXN+5];
int main(){
scanf("%d",&n);sieve(n);
for(int i=2;i<=n;i++){
int tmp=i;mul[i]=1;
while(tmp^1){
int p=mnp[tmp];
while(tmp%p==0) tmp/=p;
pf[i].pb(p);mul[i]*=p;
} c1[mul[i]]++;
} pf[1].pb(1);num[1]=1;c2[1]++;
for(int i=1;i<=prcnt;i++) num[pr[i]]=n/pr[i],c2[num[pr[i]]]++;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) if(a[i]){
if(pf[i].size()!=pf[a[i]].size()) return puts("0"),0;
for(int j=0;j+1<pf[i].size();j++) if(pf[i][j]!=pf[i][j]) return puts("0"),0;
int x=pf[i].back(),y=pf[a[i]].back();
if(num[x]!=num[y]) return puts("0"),0;
if(to1[x]&&to1[x]!=y) return puts("0"),0;
if(to2[y]&&to2[y]!=x) return puts("0"),0;
if(!to1[x]&&!to2[y]) c2[num[x]]--;
to1[x]=y;to2[y]=x;c1[mul[a[i]]]--;
} int res=1;
for(int i=(fac[0]=1);i<=n;i++) fac[i]=1ll*fac[i-1]*i%MOD;
for(int i=1;i<=n;i++) res=1ll*res*fac[c1[i]]%MOD;
for(int i=1;i<=n;i++) res=1ll*res*fac[c2[i]]%MOD;
printf("%d\n",res);
return 0;
}

Codeforces 698F - Coprime Permutation(找性质)的更多相关文章

  1. Codeforces 1442D - Sum(找性质+分治+背包)

    Codeforces 题面传送门 & 洛谷题面传送门 智商掉线/ll 本来以为是个奇怪的反悔贪心,然后便一直往反悔贪心的方向想就没想出来,看了题解才发现是个 nb 结论题. Conclusio ...

  2. [Codeforces 1208D]Restore Permutation (树状数组)

    [Codeforces 1208D]Restore Permutation (树状数组) 题面 有一个长度为n的排列a.对于每个元素i,\(s_i\)表示\(\sum_{j=1,a_j<a_i} ...

  3. Atcoder Grand Contest 008 E - Next or Nextnext(乱搞+找性质)

    Atcoder 题面传送门 & 洛谷题面传送门 震惊,我竟然能独立切掉 AGC E 难度的思维题! hb:nb tea 一道 感觉此题就是找性质,找性质,再找性质( 首先看到排列有关的问题,我 ...

  4. Codeforces 1264F - Beautiful Fibonacci Problem(猜结论+找性质)

    Codeforces 题面传送门 & 洛谷题面传送门 一道名副其实(beautiful)的结论题. 首先看到这道设问方式我们可以很自然地想到套用斐波那契数列的恒等式,注意到这里涉及到 \(F_ ...

  5. Codeforces 1413F - Roads and Ramen(树的直径+找性质)

    Codeforces 题目传送门 & 洛谷题目传送门 其实是一道还算一般的题罢--大概是最近刷长链剖分,被某道长链剖分与直径结合的题爆踩之后就点开了这题. 本题的难点就在于看出一个性质:最长路 ...

  6. Codeforces 526G - Spiders Evil Plan(长链剖分+直径+找性质)

    Codeforces 题目传送门 & 洛谷题目传送门 %%%%% 这题也太神了吧 storz 57072 %%%%% 首先容易注意到我们选择的这 \(y\) 条路径的端点一定是叶子节点,否则我 ...

  7. Codeforces 1188E - Problem from Red Panda(找性质+组合数学)

    Codeforces 题面传送门 & 洛谷题面传送门 咦,题解搬运人竟是我? 一道很毒的计数题. 先转化下题意,每一次操作我们可以视作选择一种颜色并将其出现次数 \(+k\),之后将所有颜色的 ...

  8. Codeforces 1383C - String Transformation 2(找性质+状压 dp)

    Codeforces 题面传送门 & 洛谷题面传送门 神奇的强迫症效应,一场只要 AC 了 A.B.D.E.F,就一定会把 C 补掉( 感觉这个 C 难度比 D 难度高啊-- 首先考虑对问题进 ...

  9. Codeforces 1067E - Random Forest Rank(找性质+树形 dp)

    Codeforces 题面传送门 & 洛谷题面传送门 一道不知道能不能算上自己 AC 的 D1E(?) 挺有意思的结论题,结论倒是自己猜出来了,可根本不会证( 开始搬运题解 ing: 碰到这样 ...

随机推荐

  1. Convolutional Neural Network-week2编程题2(Residual Networks)

    1. Residual Networks(残差网络) 残差网络 就是为了解决深网络的难以训练的问题的. In this assignment, you will: Implement the basi ...

  2. springBoot服务整合线程池ThreadPoolTaskExecutor与@Async详解使用

    ThreadPoolExecutor:=======这个是java自己实现的线程池执行类,基本上创建线程池都是通过这个类进行的创建.ThreadPoolTaskExecutor:========这个是 ...

  3. Asp.Net mvc4 +Spring

    添加相应的引用对象.(以下全部) 修改mvc的Global.asax文件内容 需要将控制器中原来需要new出来的对象改成属性成员 添加这个属性的注入对象 再去修改spring对web.config的一 ...

  4. 王爽汇编第十章,call和ret指令

    目录 王爽汇编第十章,call和ret指令 call和ret指令概述: ret和retf ret指令 retf指令 call 和 ret 的配合使用 call指令详解 call原理 call指令所有写 ...

  5. vim 脚本,自动添加文件头部信息

    相信很多人编写脚本的时候都会在脚本头部写一些信息,记录文件生成时候,生成人姓名等 建议在自己的家目录下的 .vimrc 文件 下添加以下内容 [ autocmd BufNewFile *.sh exe ...

  6. Abp Vnext Vue3 的版本实现

    基于ABP Vnext的二次开发,前端 vue3.0,Typescript,Ant Design Vue ,Vben Admin 的后台管理框架. 技术点 Net Core5.0 ABP Vnext ...

  7. SpringCloud升级之路2020.0.x版-29.Spring Cloud OpenFeign 的解析(1)

    本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 在使用云原生的很多微服务中,比较小规模的可能直接依靠云服务中的负载均衡器进行内部域名与服务 ...

  8. node 中第三方模块的加载过程原理

    node 中第三方模块的加载过程原理 凡是第三方模块都必须通过 npm 来下载 使用的时候就可以通过require('包名') 的方式来进行加载才可以使用 不可能有任何一个第三方包和核心模块的名字是一 ...

  9. [linux]centos7.4上安装MySQL-8.0.11【完美安装】

    版本声明 centos7.4 MySQL-8.0.11 1.我用的阿里云的虚拟主机,刚从windows换到linux,需要装下常用工具 #安装下sz rz常用到上传下载的命令 yum install ...

  10. Spring Cache 带你飞(二)

    接着上一篇讲了 Spring Cache 如何被 Spring Aop 代理加载对应的代码,以及何如注入相关界面逻辑. Spring Cache 带你飞(一) 本篇我们围绕两个要点展开: 一个数据是如 ...