Divide by Zero 2018 and Codeforces Round #474 (Div. 1 + Div. 2, combined)G - Bandit Blues

Posted acjiumeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Divide by Zero 2018 and Codeforces Round #474 (Div. 1 + Div. 2, combined)G - Bandit Blues相关的知识,希望对你有一定的参考价值。

题意:求满足条件的排列,1:从左往右会遇到a个比当前数大的数,(每次遇到更大的数会更换当前数)2.从右往左会遇到b个比当前数大的数.
题解:1-n的排列,n肯定是从左往右和从右往左的最后一个数.
考虑\(S(n,m)\)是1-n排列中从左往右会遇到m个比当前数大的数,考虑把1放在最左边,即\(S(n-1,m-1)\),考虑1不在最左边,有n-1个位置,1不可能会更换\((n-1)*S(n,m)\).即\(S(n,m)=S(n-1,m-1)+(n-1)*S(n-1,m)\)
\(S(n,m)\)即第一类斯特林数.答案即\(S(n-1,a+b-2)*C(a+b-2,a-1)\)
\(S(n,*)\)的生成函数即\(\prod_i=0^n-1(x+i)\),即x的n次上升幂.
\(F_n(x)=\prod_i=0^n-1(x+i)\),\(F_n(x+n)=\prod_i=0^n-1(x+n+i)\)
\(F_2n(x)=F_n(x)*F_n(x+n)\)
\(F_n(x)=\sum_i=0^n-1a_ix^i\),\(F_n(x+n)=\sum_i=0^n-1x^i*\sum_j=i^n-1\fracj!i!*(j-i)!n^j-ia_j\)
先卷积出\(F_n(x+n)\),然后卷积出\(F_2n(x)\),当n不能整除2时,单独考虑乘(x+n-1).
递归处理,复杂度\(O(nlogn)\)

//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize(4)
//#pragma GCC optimize("unroll-loops")
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include<bits/stdc++.h>
//#include <bits/extc++.h>
#define fi first
#define se second
#define db double
#define mp make_pair
#define pb push_back
#define mt make_tuple
//#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 998244353
#define ld long double
//#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define ull unsigned long long
#define bpc __builtin_popcount
#define base 1000000000000000000ll
#define fin freopen("a.txt","r",stdin)
#define fout freopen("a.txt","w",stdout)
#define fio ios::sync_with_stdio(false);cin.tie(0)
#define mr mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
inline ll gcd(ll a,ll b)return b?gcd(b,a%b):a;
inline void sub(ll &a,ll b)a-=b;if(a<0)a+=mod;
inline void add(ll &a,ll b)a+=b;if(a>=mod)a-=mod;
template<typename T>inline T const& MAX(T const &a,T const &b)return a>b?a:b;
template<typename T>inline T const& MIN(T const &a,T const &b)return a<b?a:b;
inline ll mul(ll a,ll b,ll c)return (a*b-(ll)((ld)a*b/c)*c+c)%c;
inline ll qp(ll a,ll b)ll ans=1;while(b)if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;return ans;
inline ll qp(ll a,ll b,ll c)ll ans=1;while(b)if(b&1)ans=mul(ans,a,c);a=mul(a,a,c),b>>=1;return ans;

using namespace std;
//using namespace __gnu_pbds;

const ld pi = acos(-1);
const ull ba=233;
const db eps=1e-5;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=100000+10,maxn=2000000+10,inf=0x3f3f3f3f;

ll x[N<<3],y[N<<3];
int rev[N<<3];
void getrev(int bit)

    for(int i=0;i<(1<<bit);i++)
        rev[i]=(rev[i>>1]>>1) | ((i&1)<<(bit-1));

void ntt(ll *a,int n,int dft)

    for(int i=0;i<n;i++)
        if(i<rev[i])
            swap(a[i],a[rev[i]]);
    for(int step=1;step<n;step<<=1)
    
        ll wn=qp(3,(mod-1)/(step*2));
        if(dft==-1)wn=qp(wn,mod-2);
        for(int j=0;j<n;j+=step<<1)
        
            ll wnk=1;
            for(int k=j;k<j+step;k++)
            
                ll x=a[k];
                ll y=wnk*a[k+step]%mod;
                a[k]=(x+y)%mod;a[k+step]=(x-y+mod)%mod;
                wnk=wnk*wn%mod;
            
        
    
    if(dft==-1)
    
        ll inv=qp(n,mod-2);
        for(int i=0;i<n;i++)a[i]=a[i]*inv%mod;
    

ll f[N],inv[N];
ll C(int a,int b)

    if(a<b||a<0||b<0)return 0;
    return f[a]*inv[b]%mod*inv[a-b]%mod;

vi solve(int n)

    if(n==1)
    
        vi v=0,1;
        return v;
    
    vi te=solve(n/2);
    int sz=0,m=te.size();
    while((1<<sz)<m)sz++;sz++;
    int len=1<<sz;
    getrev(sz);
    ll p=1;
    for(int i=0;i<m;i++)
    
        x[i]=qp(n/2,m-i-1)*inv[m-i-1]%mod;
        y[i]=te[i]*f[i]%mod;
    
    for(int i=m;i<len;i++)x[i]=y[i]=0;
    ntt(x,len,1);ntt(y,len,1);
    for(int i=0;i<len;i++)x[i]=x[i]*y[i]%mod;
    ntt(x,len,-1);
    for(int i=0;i<m;i++)y[i]=x[i+m-1]*inv[i]%mod;
    for(int i=0;i<m;i++)x[i]=te[i];
    for(int i=m;i<len;i++)x[i]=y[i]=0;
    ntt(x,len,1);ntt(y,len,1);
    for(int i=0;i<len;i++)x[i]=x[i]*y[i]%mod;
    ntt(x,len,-1);
    vi v;v.resize(len+1);
    if(n&1)
    
        y[0]=n-1;y[1]=1;
        for(int i=0;i<len;i++)
            for(int j=0;j<2;j++)
            
                v[i+j]+=x[i]*y[j]%mod;
                if(v[i+j]>=mod)v[i+j]-=mod;
            
    
    else
    
        for(int i=0;i<len;i++)v[i]+=x[i];
    
    while(v.size()&&v.back()==0)v.pop_back();
    return v;

int main()

    f[0]=inv[0]=1;
    for(int i=1;i<N;i++)f[i]=f[i-1]*i%mod,inv[i]=inv[i-1]*qp(i,mod-2)%mod;
    int n,a,b;scanf("%d%d%d",&n,&a,&b);
    if(a+b-1>n)return 0*puts("0");
    if(n==1)
    
        if(a==b&&a==1)puts("1");
        else puts("0");
        return 0;
    
    vi v=solve(n-1);
    printf("%lld\n",1ll*v[a+b-2]*C(a+b-2,a-1)%mod);
    return 0;

/********************

********************/

以上是关于Divide by Zero 2018 and Codeforces Round #474 (Div. 1 + Div. 2, combined)G - Bandit Blues的主要内容,如果未能解决你的问题,请参考以下文章

Divide by Zero 2021 and Codeforces Round #714 (Div. 2) ABC题解

听力Why Can’t You Divide by Zero?

Divide by Zero 2017 D&E&F

CWE-369:Divide By Zero除数有可能为零缺陷是如何产生的?

codeforces 792C. Divide by Three

CodeForce-792C Divide by Three(数学)