codeforces698f(数学)

F. Coprime Permutation
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Two positive integers are coprime if and only if they don't have a common divisor greater than 1.

Some bear doesn't want to tell Radewoosh how to solve some algorithmic problem. So, Radewoosh is going to break into that bear's safe with solutions. To pass through the door, he must enter a permutation of numbers 1 through n. The door opens if and only if an entered permutation p1, p2, ..., pn satisfies:

In other words, two different elements are coprime if and only if their indices are coprime.

Some elements of a permutation may be already fixed. In how many ways can Radewoosh fill the remaining gaps so that the door will open? Print the answer modulo 109 + 7.

Input

The first line of the input contains one integer n (2 ≤ n ≤ 1 000 000).

The second line contains n integers p1, p2, ..., pn (0 ≤ pi ≤ n) where pi = 0 means a gap to fill, and pi ≥ 1 means a fixed number.

It's guaranteed that if i ≠ j and pi, pj ≥ 1 then pi ≠ pj.

Output

Print the number of ways to fill the gaps modulo 109 + 7 (i.e. modulo 1000000007).

Examples
input
Copy
4
0 0 0 0
output
Copy
4
input
Copy
5
0 0 1 2 0
output
Copy
2
input
Copy
6
0 0 1 2 0 0
output
Copy
0
input
Copy
5
5 3 4 2 1
output
Copy
0
Note

In the first sample test, none of four element is fixed. There are four permutations satisfying the given conditions: (1,2,3,4), (1,4,3,2), (3,2,1,4), (3,4,1,2).

In the second sample test, there must be p3 = 1 and p4 = 2. The two permutations satisfying the conditions are: (3,4,1,2,5), (5,4,1,2,3).



题意:构造一个1到n的排列 a1,a2,......an a1,a2,......an 满足对于任意i,j满足 1<=i<j<=n 1<=i<j<=n  ai,aj ai,aj 互质当且仅当i,j互质。a中一些元素已知,求可以构造的排列个数。

对于两个质数p1,p2,如果有这两个质数因子的数的个数相等(既n/p1=n/p2)那么可以将所有数的质因子中出现的这两个质数交换。

如果两个数包含相同的质因子,那么可以将两个数交换。

如果第i个数ai已知: 
如果ai质因子个数和i的质因子个数不等,无解。 
如果ai的第j个质因子和i的第j个质因子出现次数不等,无解。 
注意设ai有pi个质因子,这里只需要判断前pi-1个质因子是否相等和第pi个质因子出现次数是否相等即可。因为前pi-1个质因子小于根号n,对于小于根号n的两个质数p1,p2:n/p1和n/p2不等。 
如果最后一个质因子已经有对应的质因子,无解。

最后阶乘统计答案即可。

注意处理1的问题。


#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define ll long long
#define N 1100000
int n;
ll jc[N],ans;
int a[N],num[N],num1[N],pos[N],mul[N];
int pres[N],nex[N];
vector<int>v[N];  //每个数包含的质因数 
void quit(){puts("0");exit(0);}
int main()
{
    scanf("%d",&n);
    //阶乘预处理 
    jc[0]=1;
    for(int i=1;i<=n;i++)jc[i]=jc[i-1]*i%mod;
    
    for(int i=1;i<=n;i++)mul[i]=1;
    for(int i=2,pre_=0;i<=n;i++)
        if(!v[i].size())  //是质数 
        {
            num[n/i]++;
			pos[i]=n/i;
            for(int j=i;j<=n;j+=i)
                v[j].push_back(i),mul[j]*=i;  //mul[j]表示包含有j的所有质因数的最小的数 
        }
    for(int i=1;i<=n;i++)num1[mul[i]]++;   //每种质因数组合(不计个数)包含的数的总数 
    num[1]++;pos[1]=1;
    v[1].push_back(1);

    for(int i=1,x,y;i<=n;i++)
    {
        scanf("%d",&a[i]);
        if(a[i]==0)continue;
        num1[mul[a[i]]]--;  //第一类情况 
        if(v[a[i]].size()!=v[i].size())quit();
        for(int j=0;j<v[i].size()-1;j++)
            if(v[a[i]][j]!=v[i][j])quit();
        x=v[a[i]].back();y=v[i].back();
        if(pos[x]!=pos[y])quit();  //最大质因数个数不同 
        if(pres[x]&&pres[x]!=y)quit();   //
        if(nex[y]&&nex[y]!=x)quit();
        if(!pres[x]&&!nex[y])num[pos[x]]--;   //
        pres[x]=y;nex[y]=x;
    }
    ans=1;
    for(int i=1;i<=n;i++)
		ans=ans*jc[num1[i]]%mod;
    for(int i=1;i<=n;i++)
		ans=ans*jc[num[i]]%mod;
    printf("%I64d\n",ans);
    return 0;
}


以上内容参考自:https://blog.csdn.net/make_it_for_good/article/details/52301021

侵删

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值