zoukankan      html  css  js  c++  java
  • codeforces960G. Bandit Blues

    题目链接:codeforces960G

    来看看三倍经验:hdu4372 luogu4609

    某蒟蒻的关于第一类斯特林数的一点理解QAQ:https://www.cnblogs.com/zhou2003/p/10780832.html

    注意到当前序列的最大值会对前缀最大值和后缀最大值均产生(1)的贡献

    那么当我们去掉这个最大值后,剩下(n-1)个元素,需要产生(a-1)个前缀最大值和(b-1)个后缀最大值,并且它们的位置会以最大值为界限分布在两侧

    我们将剩下的(n-1)个元素分成((a-1)+(b-1))组,每一组钦定最大值在最开头,那么每一个这样的划分就对应了一个合法的序列,最后答案就是(S(n-1,a+b-2)*dbinom{a+b-2}{a-1}),其中(S(n,m))表示第一类斯特林数

    这样你就可以完成后两题了

    那么对于第一题呢?我们有这个式子:

    [S(n,m)=[x^m]prod_{i=0}^{n-1}(x+i) ]

    于是分治+FFT求之,据说有(O(nlogn))的倍增做法?我懒啊

    #include<iostream>
    #include<string.h>
    #include<string>
    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    using namespace std;
    #define lowbit(x) (x)&(-x)
    #define rep(i,a,b) for (int i=a;i<=b;i++)
    #define per(i,a,b) for (int i=a;i>=b;i--)
    #define maxd 998244353
    typedef long long ll;
    const int N=100000;
    const double pi=acos(-1.0);
    int n,a,b,rev[400400];
    ll s[20][400400];
    
    int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    	while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    	return x*f;
    }
    
    ll qpow(ll x,int y)
    {
    	ll ans=1;
    	while (y)
    	{
    		if (y&1) ans=(ans*x)%maxd;
    		x=(x*x)%maxd;
    		y>>=1;
    	}
    	return ans;
    }
    
    ll inv(ll x) {return qpow(x,maxd-2);}
    
    ll C(int n,int m)
    {
    	if (n<m) return 0;
    	ll ans=1;
    	per(i,n,n-m+1) ans=ans*i%maxd;
    	rep(i,1,m) ans=ans*inv(i)%maxd;
    	return ans;
    }
    
    void ntt(int lim,ll *a,int typ)
    {
    	rep(i,0,lim-1)
    		if (i<rev[i]) swap(a[i],a[rev[i]]);
    	int mid;
    	for (mid=1;mid<lim;mid<<=1)
    	{
    		ll wn=qpow(3,(maxd-1)/(mid<<1));
    		int len=(mid<<1),sta,j;
    		if (typ==-1) wn=inv(wn);
    		for (sta=0;sta<lim;sta+=len)
    		{
    			ll w=1;
    			for (j=0;j<mid;j++,w=(w*wn)%maxd)
    			{
    				ll x=a[sta+j],y=a[sta+j+mid]*w%maxd;
    				a[sta+j]=(x+y)%maxd;
    				a[sta+j+mid]=(x+maxd-y)%maxd;
    			}
    		}
    	}
    	if (typ==-1)
    	{
    		int invn=inv(lim);
    		rep(i,0,lim-1) a[i]=a[i]*invn%maxd;
    	}
    }
    
    void solve(int l,int r,int d)
    {
    	if (l==r) {s[d][0]=l;s[d][1]=1;return;}
    	int mid=(l+r)>>1;
    	solve(l,mid,d+1);
    	rep(i,0,mid-l+1) s[d][i]=s[d+1][i];
    	solve(mid+1,r,d+1);
    	int lim=1,cnt=0;
    	while (lim<=(r-l+1)) {lim<<=1;cnt++;}
    	rep(i,mid-l+2,lim) s[d][i]=0;
    	rep(i,r-mid+1,lim) s[d+1][i]=0;
    	rep(i,0,lim-1)
    		rev[i]=(rev[i>>1]>>1)|((i&1)<<(cnt-1));
    	ntt(lim,s[d],1);ntt(lim,s[d+1],1);
    	rep(i,0,lim-1) s[d][i]=s[d][i]*s[d+1][i]%maxd;
    	ntt(lim,s[d],-1);
    }
    
    int main()
    {
    	n=read();a=read();b=read();
    	if ((n-1<a+b-2) || (!a) || (!b)) {printf("0");return 0;}
    	if (n==1) {printf("1");return 0;}
    	solve(0,n-2,0);
    	printf("%lld",C(a+b-2,a-1)*s[0][a+b-2]%maxd);
    	return 0;
    }
    
  • 相关阅读:
    python json 和 pickle的补充 hashlib configparser logging
    go 流程语句 if goto for swich
    go array slice map make new操作
    go 基础
    块级元素 行内元素 空元素
    咽炎就医用药(慢性肥厚性咽炎)
    春季感冒是风寒还是风热(转的文章)
    秋季感冒 咳嗽 怎么选药
    解决IE浏览器“无法显示此网页”的问题
    常用的 css 样式 记录
  • 原文地址:https://www.cnblogs.com/encodetalker/p/10780541.html
Copyright © 2011-2022 走看看