hdu第十场Cyclic

本题主要是对用容斥的使用,正难则反,对于要求满足题意的可以求不满足题意的

先考虑对于长度至少为2的连续序列,易得其排列C(n,1)*(n-2)!,意为从剩下n个数字中选取连续的两个。

方法总计为n,即从n种中选取一个,剩下所有元素进行全排列

由此可以类比到选取k(0-n-1)个连续的元素,即排列总数为C(n,k)(n-k-1)!

当k==n为一个的时候答案总为1

再运用容斥的原理可以得到其为

ans=(-1)^n+sum((-1)^k*c(n,k)(n-k-1)!,0-(n-1))

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
const int mod=998244353;
typedef long long int ll;

ll pre[maxn+5],inv[maxn+5],n;
ll powmod(ll a,ll b)
{
    ll ans=1;
    a=a%mod;
    while(b)
    {
        if(b&1)ans=(a%mod*ans%mod)%mod;
        a=(a%mod*a%mod)%mod;
        b>>=1;
    }
    return ans%mod;
}
ll c(ll n,ll m)
{
    return 1ll*((pre[n]%mod*inv[n-m]%mod)%mod*inv[m]%mod)%mod;
}
void solve()
{
    scanf("%d",&n);
    ll ans=((n%2==0)?1:mod-1);
    for(int i=0; i<n; i++)
    {
        ll an=(c(n,i)%mod*pre[n-i-1]%mod)%mod;
        if(i&1)
        {
            (ans += mod- an) %= mod;
        }
        else
        {
            (ans += an) %= mod;
        }
    }
    printf("%lld\n",(ans+mod)%mod);
}
int main()
{
    pre[0]=1;
    for(int i=1; i<=maxn; i++)
    {
        pre[i]=(pre[i-1]%mod*i%mod)%mod;
    }
    inv[maxn]=powmod(pre[maxn],mod-2);
    for(int i=maxn-1; i>=0; i--)
    {
        inv[i]=(inv[i+1]%mod*(i+1)%mod)%mod;
    }
    int t;
    for(scanf("%d",&t); t; t--)
    {
        solve();
    }
    return 0;
}
View Code

 

posted @ 2018-08-22 20:16  nlc_x  阅读(97)  评论(0编辑  收藏  举报