Codeforces 698F - Coprime Permutation(找性质)
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(找性质)的更多相关文章
- Codeforces 1442D - Sum(找性质+分治+背包)
Codeforces 题面传送门 & 洛谷题面传送门 智商掉线/ll 本来以为是个奇怪的反悔贪心,然后便一直往反悔贪心的方向想就没想出来,看了题解才发现是个 nb 结论题. Conclusio ...
- [Codeforces 1208D]Restore Permutation (树状数组)
[Codeforces 1208D]Restore Permutation (树状数组) 题面 有一个长度为n的排列a.对于每个元素i,\(s_i\)表示\(\sum_{j=1,a_j<a_i} ...
- Atcoder Grand Contest 008 E - Next or Nextnext(乱搞+找性质)
Atcoder 题面传送门 & 洛谷题面传送门 震惊,我竟然能独立切掉 AGC E 难度的思维题! hb:nb tea 一道 感觉此题就是找性质,找性质,再找性质( 首先看到排列有关的问题,我 ...
- Codeforces 1264F - Beautiful Fibonacci Problem(猜结论+找性质)
Codeforces 题面传送门 & 洛谷题面传送门 一道名副其实(beautiful)的结论题. 首先看到这道设问方式我们可以很自然地想到套用斐波那契数列的恒等式,注意到这里涉及到 \(F_ ...
- Codeforces 1413F - Roads and Ramen(树的直径+找性质)
Codeforces 题目传送门 & 洛谷题目传送门 其实是一道还算一般的题罢--大概是最近刷长链剖分,被某道长链剖分与直径结合的题爆踩之后就点开了这题. 本题的难点就在于看出一个性质:最长路 ...
- Codeforces 526G - Spiders Evil Plan(长链剖分+直径+找性质)
Codeforces 题目传送门 & 洛谷题目传送门 %%%%% 这题也太神了吧 storz 57072 %%%%% 首先容易注意到我们选择的这 \(y\) 条路径的端点一定是叶子节点,否则我 ...
- Codeforces 1188E - Problem from Red Panda(找性质+组合数学)
Codeforces 题面传送门 & 洛谷题面传送门 咦,题解搬运人竟是我? 一道很毒的计数题. 先转化下题意,每一次操作我们可以视作选择一种颜色并将其出现次数 \(+k\),之后将所有颜色的 ...
- Codeforces 1383C - String Transformation 2(找性质+状压 dp)
Codeforces 题面传送门 & 洛谷题面传送门 神奇的强迫症效应,一场只要 AC 了 A.B.D.E.F,就一定会把 C 补掉( 感觉这个 C 难度比 D 难度高啊-- 首先考虑对问题进 ...
- Codeforces 1067E - Random Forest Rank(找性质+树形 dp)
Codeforces 题面传送门 & 洛谷题面传送门 一道不知道能不能算上自己 AC 的 D1E(?) 挺有意思的结论题,结论倒是自己猜出来了,可根本不会证( 开始搬运题解 ing: 碰到这样 ...
随机推荐
- 深入理解java中main方法
理解main方法语法 深入理解main方法: 解释main方法的形式:public static void main(String[] args){} main方法调用者:虚拟机 java虚拟机需要调 ...
- 【UE4 C++】 UDataAsset、UPrimaryDataAsset 的简单使用
UDataAsset 简介 用来存储数据,每一个DataAsset 都是一份数据 可以派生,系统自带派生 UPrimaryDataAsset 方便数据对象的加载和释放 可以引用其他的 UDataAss ...
- 2021.10.18考试总结[NOIP模拟76]
T1 洛希极限 不难发现每个点肯定是被它上一行或上一列的点转移.可以预处理出每个点上一行,上一列最远的能转移到它的点,然后单调队列优化. 预处理稍显ex.可以用并查集维护一个链表,记录当前点之后第一个 ...
- 震惊,hzoi的分差竟然折磨大,活到爆!
众所周知,hzoi的分差非常"大",那么究竟有多大呢?最近,一位外国小哥开发出了hzoi的分差竟然折磨大,活到爆!的方法,这究竟是怎么一回事呢?快和小编一起来看看吧- 竟然1分就可 ...
- MyBatis源码分析(八):设计模式
Mybatis中用到的设计模式 1. 建造者(Builder)模式: 表示一个类的构建与类的表示分离,使得同样的构建过程可以创建不同的表示.建造者模式是一步一步创建一个复杂的对象,他只允许用户只通过指 ...
- C++实现红黑树
红黑树的应用: 利用key_value对,快速查找,O(logn) socket与客户端id之间,形成映射关系(socket, id) 内存分配管理 一整块内存,不断分配小块 每分配一次,就加入到红黑 ...
- copy-list-with-random-pointer leetcode C++
A linked list is given such that each node contains an additional random pointer which could point t ...
- 面试官:能手写实现call、apply、bind吗?
1 call.apply.bind 用法及对比 1.1 Function.prototype 三者都是Function原型上的方法,所有函数都能调用它们 Function.prototype.call ...
- 解决虚拟机安装linux系统无法全屏问题 & vmtools安装
修改设置 1) 如下图右单击虚拟机名,选择[settings-],调出虚拟机设置界面. 2) 在设置界面选择[hardware]->[CD/DVD2(IDE)]->[Connection] ...
- 4. 理解Update、Enter、Exit 与 添加、删除元素
理解Update.Enter.Exit 与 添加.删除元素 在使用data()绑定数据时,例如:现在我们有一个数组[3,6,9,12,15],我们可以将数组每一项与一个<p>绑定,但是,现 ...