zoukankan      html  css  js  c++  java
  • CF698F Coprime Permutation

    题意:求有多少种符合要求的排列满足对于所有i,j,当gcd(i,j)=1时,gcd(pi,pj)=1。

    排列上的一些位置给出。

    标程:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int mod=1e9+7;
     5 const int N=1000005;
     6 int n,p[N],cnt[N],Cnt[N],base[N],To1[N],To2[N],jc[N],x,ans;
     7 vector<int> fac[N]; 
     8 void fail(){puts("0");exit(0);}//这个东西超级好用!
     9 void shai()
    10 {
    11     for (int i=2;i<=n;i++)
    12     if (!p[i])
    13     {
    14         cnt[n/i]++;
    15         for (int j=i;j<=n;j+=i)
    16         {
    17             p[j]=1;base[j]*=i;
    18             fac[j].push_back(i);
    19         }
    20     }
    21 }
    22 void check(int x,int y)
    23 {
    24    if (fac[x].size()!=fac[y].size()) fail();
    25    for (int i=0;i<fac[x].size();i++)
    26    {
    27        int fu=fac[x][i],fv=fac[y][i];
    28        int u=(x==1)?1:n/fu,v=(y==1)?1:n/fv;
    29        if (u!=v) fail();
    30        if (To1[fu]&&To1[fu]!=fv) fail();
    31        if (To2[fv]&&To2[fv]!=fu) fail();
    32        if (!To2[fv]) To1[fu]=fv,To2[fv]=fu,cnt[u]--;
    33     }
    34     Cnt[base[x]]--;
    35 }
    36 int main()
    37 {
    38     scanf("%d",&n);
    39     jc[0]=1;cnt[1]=1;//1和所有数互质!!! 
    40     for (int i=1;i<=n;i++) jc[i]=(ll)jc[i-1]*i%mod,base[i]=1;
    41     shai();fac[1].push_back(1);//!!!
    42     for (int i=1;i<=n;i++) Cnt[base[i]]++; 
    43     for (int i=1;i<=n;i++) 
    44     {
    45        scanf("%d",&x);
    46        if (x) check(i,x);
    47    } 
    48    ans=1;
    49    for (int i=1;i<=n;i++)
    50      ans=(ll)ans*jc[cnt[i]]%mod*jc[Cnt[i]]%mod;
    51    printf("%d
    ",ans);
    52    return 0;
    53 }

    易错点:1.注意1和所有数互质,所以cnt[1]=1,表示1~n和1不互质的只有1个数。

    2.fac[1].push_back(1),1有一个因数为1,小心判错。

    题解:数学+性质

    一开始我想分别求出与每个数互质的数的个数,较难。

    发现可以从什么样的数相互交换等价入手:1.两个数的因数种类完全一样。2.若质数p1,p2,且[n/p1]=[n/p2]时,即1~n中所有p1的倍数和p2的倍数可以一一对应,那么对应互换。这两个交换相互独立。

    如果没有固定元素这样就结束了。

    判断合法性:

    1.两个元素的因数去重后的个数要一样。

    2.两个限制可以合并为对应因数的出现次数一样。

    3.质因子之间产生轮换,可以会产生矛盾,要判掉。

    最后减去已经确定的答案。

    实现的时候有一些小技巧:

    1.比较因数种类完全一样时,相当于比较两个数所有质因子的一次乘积。

    2.可以用素数筛求出所有质数并筛出每个数的因数种类。

    3.当p1,p2<=n^0.5时,[n/p1]与[n/p2]必然不等。

  • 相关阅读:
    NDOC中文支持及入门用法
    网页代码常用小技巧
    SOCKET通讯点滴
    自动备份程序目录
    MySql.Data.dll Microsoft.Web.UI.WebControls.dll下载
    c#:获取IE地址栏中的URL
    比较好的单例登录模式(参考网友)
    FreeTextBox使用详解
    2005自定义控件显示基准线
    连接字符串大全
  • 原文地址:https://www.cnblogs.com/Scx117/p/9076095.html
Copyright © 2011-2022 走看看