• hdu 6432 Cyclic


    题意:

    计算长度为n且不含有子串[i,i+1]或[n,1]的不同循环排列的个数。

    解法:

    拿n=4举例,即不含12,23,34,41这样的子串。

    首先先说明什么是循环排列:

    即把1-n这n个数随意地放到一个圆圈上,循环排列的不同仅仅取决于这n个数的相对位置的不同。

    例如1234,2341,3412,4123这些数为相同的循环排列数。

    循环排列没有首末之分,这四个元素随便从哪一个元素开始,绕一个方向转过去,都不改变它们的相对顺序;直线排列则首末分明,原来排末位,调换排首位,已改变它们的相对顺序。循环排列与直线排列的主要区别就在这一点上。

    从例子看出,直线排列的个数是循环排列个数的n倍

    由直线排列个数为n!可推知循环排列个数为(n-1)!。

    讲完了循环排列,再来看此题是求不含子串[i,i+1]或[n,1](以下简称顺序子串,共有n个)的循环排列个数

    因为一个排列中可能含有多个顺序子串,所以我们列举至少含有0个,1个,...n个的情况  (注意是至少,因为无法保证恰好含有i个)

    包含至少一个顺序子串的循环排列数为C(n,1)*(n-2)!

    包含至少两个顺序子串的循环排列数为C(n,2)*(n-3)!

    ...

    包含至少k个顺序子串的循环排列数为C(n,k)*(n-k-1)! 

    (为什么是(n-k-1)! 当你选出了k个子串之后,至少有k+1个数相对位置已被确定,我们让剩下的(n-k-1)个数全排列即可。)

    同时注意到包含n个顺序子串的循环排列数一定是1个。

    事件之间相互包含,所以用到容斥原理:

     ∑(k从0到n-1)(-1)^k*C(n,k)*(n-k-1)!+(-1)^n*1

    同样预处理阶乘及阶乘的逆元。

    AC代码:

     1 #include <bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4 const int mod=998244353;
     5 const int maxn=1e5+10;
     6 ll fac[maxn],invfac[maxn],inv[maxn];
     7 void init()
     8 {
     9     int i;
    10     inv[1]=1;
    11     for(i=2;i<maxn;i++)
    12     {
    13         inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod;
    14     }
    15     fac[0]=1;
    16     invfac[0]=1;
    17     for(i=1;i<maxn;i++)
    18     {
    19         fac[i]=(ll)fac[i-1]*i%mod;
    20         invfac[i]=(ll)invfac[i-1]*inv[i]%mod;
    21     }
    22 }
    23 ll C(int n,int m)
    24 {
    25     if(n<0||m<0||m>n)return 0;
    26     return (ll)fac[n]*invfac[m]%mod*invfac[n-m]%mod;
    27 }
    28 int main()
    29 {
    30     int t;
    31     cin>>t;
    32     init();
    33     while(t--)
    34     {
    35         int n,k;
    36         scanf("%d",&n);
    37         ll ans=0;
    38         for(k=0;k<=n-1;k++)
    39         {
    40             if(k&1)
    41             {
    42                 ans=(ans-(ll)C(n,k)*fac[n-k-1]%mod+mod)%mod;
    43             }
    44             else ans=(ans+(ll)C(n,k)*fac[n-k-1]%mod)%mod;
    45         }
    46         if(n&1)ans-=1;
    47         else ans+=1;
    48         printf("%I64d
    ",ans);
    49     }
    50     return 0;
    51 }
  • 相关阅读:
    Tempter of the Bone 搜索---奇偶性剪枝
    uestc 1709 Binary Operations 位运算的灵活运用
    uestc 1072 a ^ b
    uestc Another LCIS
    武汉邀请赛 Key Logger 双向链表
    bnu 29378 Adidas vs Adivon 基础题
    中南月赛F ZZY and his little friends
    日期问题
    开灯问题
    开灯问题
  • 原文地址:https://www.cnblogs.com/raincle/p/9521266.html
Copyright © 2020-2023  润新知