CF1671F
前言
有没有一种可能,就是说,出题人打着 dp 的名号,考你生成函数?
思路
我们称一个范围是 \([l,r]\) 的段是置换的,当且仅当其值域也恰遍取 \([l,r]\)。
我们称一个置换段是本原的,当且仅当其不能由其余置换段简单拼接而成。
我们称一个本原段是平凡的,当且仅当其长度为 \(1\);反之,则是不平凡的。
有结论:
- 值域为 \([l,r]\) 的置换段 \(a_{l\sim r}\) 与长度为 \(r-l+1\) 的排列 \(p_{1\sim r-l+1}\) 构成一一映射 \(p_k=a_{k+l-1}-l+1\),且保持逆序数、下降数不变。
- 任何一个长度为 \(l\) 的本原段其逆序数 \(k\ge l-1\)。
- 任何一个排列可以由若干本原段拼接而成,其中不平凡的段数量不会超过原排列的逆序数。
证明显然,略去。
注意到本题 \(k,x\) 很小,我们不妨预处理时暴力枚举所有排列,即枚举每一类置换段的形式,记录有非平凡本原性、长度为 \(l(l\le12)\)、逆序数为 \(k(k\le11)\)、下降数为 \(x(x\le11)\) 的排列数量 CNT[l][k][x]
。
这部分复杂度是 \(O(k!)\) 级别的,实际在 \(l=12\) 时要跑得巨慢,建议打表。(似乎可用多项式 \(\ln\) 来解决而不用暴力?)
记生成函数 \(F(z)=\sum_{a,b,c}(Cnt_{a,b,c}u^bt^c)z^a\)(注意这里认为 \(u,t\) 都是常数),则答案的生成函数为:
\[{1\over1-z-F}
\]
答案为
\[\\
[z^nu^kt^x]{1\over1-z-F}
\\=[z^nu^kt^x]\sum_a\sum_p\binom{a+p}pz^aF^p\quad({\tt 这步用组合意义解释更简单})
\\=\sum_a[z^{n-a}u^kt^x]\sum_p\binom{a+p}pF^p
\\=\sum_a\sum_p\binom{n-a+p}p[z^au^kt^x]F^p
\\\]
(其实用组合意义解释更简单,可以避免生成函数)
由于 \(k,x\) 的限制,暴力预处理 \(F^1,F^2,\dots,F^{11}\) 即可,于是 \(a\le22\) 也是显然的,从而这个柿子可以暴力求。
综上,本题解完。
Code
如果常数实现不优秀,可能要考虑加一个火车头。
注释里的代码用于 CNT[12][][]
的打表卡常。
#include <algorithm>
#include <stdio.h>
#include <vector>
typedef long long llt;
typedef unsigned uint;typedef unsigned long long ullt;
typedef bool bol;typedef char chr;typedef void voi;
typedef double dbl;
template<typename T>bol _max(T&a,T b){return(a<b)?a=b,true:false;}
template<typename T>bol _min(T&a,T b){return(b<a)?a=b,true:false;}
template<typename T>T lowbit(T n){return n&-n;}
template<typename T>T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<typename T>T lcm(T a,T b){return(a!=0||b!=0)?a/gcd(a,b)*b:(T)0;}
template<typename T>T exgcd(T a,T b,T&x,T&y){if(b!=0){T ans=exgcd(b,a%b,y,x);y-=a/b*x;return ans;}else return y=0,x=1,a;}
template<typename T>T power(T base,T index,T mod)
{
T ans=1%mod;
while(index)
{
if(index&1)ans=ans*base%mod;
base=base*base%mod,index>>=1;
}
return ans;
}
namespace ConstMod
{
template<const ullt p>
class mod_ullt
{
private:
ullt v;
inline ullt chg(ullt w){return(w<p)?w:w-p;}
inline mod_ullt _chg(ullt w){mod_ullt ans;ans.v=(w<p)?w:w-p;return ans;}
public:
mod_ullt():v(0){}
mod_ullt(ullt v):v(v%p){}
bol empty(){return!v;}
inline ullt val(){return v;}
friend bol operator<(mod_ullt a,mod_ullt b){return a.v<b.v;}
friend bol operator>(mod_ullt a,mod_ullt b){return a.v>b.v;}
friend bol operator<=(mod_ullt a,mod_ullt b){return a.v<=b.v;}
friend bol operator>=(mod_ullt a,mod_ullt b){return a.v>=b.v;}
friend bol operator==(mod_ullt a,mod_ullt b){return a.v==b.v;}
friend bol operator!=(mod_ullt a,mod_ullt b){return a.v!=b.v;}
inline friend mod_ullt operator+(mod_ullt a,mod_ullt b){return a._chg(a.v+b.v);}
inline friend mod_ullt operator-(mod_ullt a,mod_ullt b){return a._chg(a.v+a.chg(p-b.v));}
inline friend mod_ullt operator*(mod_ullt a,mod_ullt b){return a.v*b.v;}
friend mod_ullt operator/(mod_ullt a,mod_ullt b){return b._power(p-2)*a.v;}
friend mod_ullt operator^(mod_ullt a,ullt b){return a._power(b);}
inline mod_ullt operator-(){return _chg(p-v);}
mod_ullt sqrt()
{
if(power(v,(p-1)>>1,p)!=1)return 0;
mod_ullt b=1;do b++;while(b._power((p-1)>>1)==1);
ullt t=p-1,s=0,k=1;while(!(t&1))s++,t>>=1;
mod_ullt x=_power((t+1)>>1),e=_power(t);
while(k<s)
{
if(e._power(1llu<<(s-k-1))!=1)x*=b._power((1llu<<(k-1))*t);
e=_power(p-2)*x*x,k++;
}
return _min(x,-x),x;
}
mod_ullt inv(){return _power(p-2);}
mod_ullt _power(ullt index){mod_ullt ans(1),w(v);while(index){if(index&1)ans*=w;w*=w,index>>=1;}return ans;}
voi read(){v=0;chr c;do c=getchar();while(c>'9'||c<'0');do v=(c-'0'+v*10)%p,c=getchar();while(c>='0'&&c<='9');v%=p;}
voi print()
{
static chr C[20];uint tp=0;
ullt w=v;do C[tp++]=w%10+'0',w/=10;while(w);
while(tp--)putchar(C[tp]);
}
voi println(){print(),putchar('\n');}
mod_ullt operator++(int){mod_ullt ans=*this;return v=chg(v+1),ans;}
public:
inline ullt&operator()(){return v;}
inline mod_ullt&operator+=(mod_ullt b){return*this=_chg(v+b.v);}
inline mod_ullt&operator-=(mod_ullt b){return*this=_chg(v+chg(p-b.v));}
inline mod_ullt&operator*=(mod_ullt b){return*this=v*b.v;}
mod_ullt&operator^=(ullt b){return*this=_power(b);}
mod_ullt&operator/=(mod_ullt b){return*this=b._power(p-2)*v;}
mod_ullt&operator++(){return v=chg(v+1),*this;}
};
}
const ullt Mod=998244353;
typedef ConstMod::mod_ullt<Mod>modint;
modint A[100005],B[100005];
modint CNT[13][12][12],User[12][27][12][12];
uint V[13],QAQ[13];
int main() // 总不会手写 ln 吧???
{
#ifdef MYEE
freopen("QAQ.in","r",stdin);
#endif
A[0]=1;for(uint i=1;i<=100000;i++)A[i]=A[i-1]*i;
B[100000]=A[100000].inv();for(uint i=100000;i;i--)B[i-1]=B[i]*i;
for(uint i=2;i<=11;i++)
{
for(uint j=0;j<i;j++)V[j]=j+1;
V[i-1]=0;
do
{
if(V[i-1]==i-1)continue;
uint p=0;
for(uint j=0;j<i;j++){_max(p,V[j]);if(p==j)break;}
if(++p!=i)
{
for(uint j=p;j<i;j++)V[j]=i+p-1-j;
continue;
}
for(uint j=0;j<i;j++)QAQ[j]=0;
uint x=0,y=0;
for(uint j=i-1;~j;j--)
{
for(uint k=V[j];k;k-=lowbit(k))x+=QAQ[k];
for(uint k=V[j]+1;k<=i;k+=lowbit(k))QAQ[k]++;
}
for(uint j=1;j<i;j++)y+=V[j-1]>V[j];
if(x<=11&&y<=11)CNT[i][x][y]++;
}
while(std::next_permutation(V,V+i));
// puts("qwq");
}
// for(uint i=1;i<=11;i++)for(uint j=1;j<=11;j++)
// CNT[12][i][j].print(),putchar(" \n"[j==11]);
CNT[12][11][1]=11;CNT[12][11][2]=165;CNT[12][11][3]=462;CNT[12][11][4]=330;CNT[12][11][5]=55;CNT[12][11][6]=1;
// for(uint i=1;i<=5;i++)for(uint j=1;j<=5;j++)for(uint k=1;k<=5;k++)
// CNT[i][j][k].print(),putchar(" \n"[k==5]);
User[0][0][0][0]=1;
for(uint p=1;p<=11;p++)for(uint i=1;i<=12;i++)for(uint j=1;j<=11;j++)for(uint k=1;k<=11;k++)
for(uint q=24;q>=i;q--)for(uint u=11;u>=j;u--)for(uint v=11;v>=k;v--)
User[p][q][u][v]+=User[p-1][q-i][u-j][v-k]*CNT[i][j][k];
uint t;scanf("%u",&t);
while(t--)
{
uint n,k,t;
scanf("%u%u%u",&n,&k,&t);
auto binom=[&](uint n,uint k)->modint
{
if(n<k||n>Mod||k>Mod)return 0;
modint ans=B[k];
for(uint i=n-k+1;i<=n;i++)ans*=i;
return ans;
};
modint ans;
for(uint i=1;i<=22&&i<=n;i++)for(uint j=1;j<=11;j++)ans+=binom(n-i+j,j)*User[j][i][k][t];
ans.println();
}
return 0;
}
再来放张表(可以通过在上面代码基础上修改得到):
CNT[2][1][1]=1;
CNT[3][2][1]=2;
CNT[3][3][2]=1;
CNT[4][3][1]=3;CNT[4][3][2]=1;
CNT[4][4][1]=1;CNT[4][4][2]=4;
CNT[4][5][2]=3;
CNT[4][6][3]=1;
CNT[5][4][1]=4;CNT[5][4][2]=4;
CNT[5][5][1]=2;CNT[5][5][2]=12;CNT[5][5][3]=2;
CNT[5][6][1]=2;CNT[5][6][2]=12;CNT[5][6][3]=4;
CNT[5][7][2]=9;CNT[5][7][3]=6;
CNT[5][8][2]=3;CNT[5][8][3]=6;
CNT[5][9][3]=4;
CNT[5][10][4]=1;
CNT[6][5][1]=5;CNT[6][5][2]=10;CNT[6][5][3]=1;
CNT[6][6][1]=3;CNT[6][6][2]=28;CNT[6][6][3]=13;
CNT[6][7][1]=4;CNT[6][7][2]=35;CNT[6][7][3]=29;CNT[6][7][4]=1;
CNT[6][8][1]=3;CNT[6][8][2]=35;CNT[6][8][3]=41;CNT[6][8][4]=4;
CNT[6][9][1]=1;CNT[6][9][2]=30;CNT[6][9][3]=44;CNT[6][9][4]=7;
CNT[6][10][2]=17;CNT[6][10][3]=45;CNT[6][10][4]=7;
CNT[6][11][2]=8;CNT[6][11][3]=30;CNT[6][11][4]=11;
CNT[7][6][1]=6;CNT[7][6][2]=20;CNT[7][6][3]=6;
CNT[7][7][1]=4;CNT[7][7][2]=55;CNT[7][7][3]=50;CNT[7][7][4]=3;
CNT[7][8][1]=6;CNT[7][8][2]=80;CNT[7][8][3]=118;CNT[7][8][4]=18;
CNT[7][9][1]=6;CNT[7][9][2]=95;CNT[7][9][3]=186;CNT[7][9][4]=48;
CNT[7][10][1]=6;CNT[7][10][2]=101;CNT[7][10][3]=230;CNT[7][10][4]=85;CNT[7][10][5]=2;
CNT[7][11][1]=2;CNT[7][11][2]=94;CNT[7][11][3]=260;CNT[7][11][4]=113;CNT[7][11][5]=4;
CNT[8][7][1]=7;CNT[8][7][2]=35;CNT[8][7][3]=21;CNT[8][7][4]=1;
CNT[8][8][1]=5;CNT[8][8][2]=96;CNT[8][8][3]=145;CNT[8][8][4]=26;
CNT[8][9][1]=8;CNT[8][9][2]=155;CNT[8][9][3]=358;CNT[8][9][4]=124;CNT[8][9][5]=3;
CNT[8][10][1]=9;CNT[8][10][2]=207;CNT[8][10][3]=616;CNT[8][10][4]=313;CNT[8][10][5]=16;
CNT[8][11][1]=11;CNT[8][11][2]=250;CNT[8][11][3]=859;CNT[8][11][4]=567;CNT[8][11][5]=53;
CNT[9][8][1]=8;CNT[9][8][2]=56;CNT[9][8][3]=56;CNT[9][8][4]=8;
CNT[9][9][1]=6;CNT[9][9][2]=154;CNT[9][9][3]=350;CNT[9][9][4]=126;CNT[9][9][5]=4;
CNT[9][10][1]=10;CNT[9][10][2]=268;CNT[9][10][3]=898;CNT[9][10][4]=552;CNT[9][10][5]=48;
CNT[9][11][1]=12;CNT[9][11][2]=389;CNT[9][11][3]=1654;CNT[9][11][4]=1404;CNT[9][11][5]=204;CNT[9][11][6]=1;
CNT[10][9][1]=9;CNT[10][9][2]=84;CNT[10][9][3]=126;CNT[10][9][4]=36;CNT[10][9][5]=1;
CNT[10][10][1]=7;CNT[10][10][2]=232;CNT[10][10][3]=742;CNT[10][10][4]=448;CNT[10][10][5]=43;
CNT[10][11][1]=12;CNT[10][11][2]=427;CNT[10][11][3]=1967;CNT[10][11][4]=1887;CNT[10][11][5]=357;CNT[10][11][6]=6;
CNT[11][10][1]=10;CNT[11][10][2]=120;CNT[11][10][3]=252;CNT[11][10][4]=120;CNT[11][10][5]=10;
CNT[11][11][1]=8;CNT[11][11][2]=333;CNT[11][11][3]=1428;CNT[11][11][4]=1302;CNT[11][11][5]=252;CNT[11][11][6]=5;
CNT[12][11][1]=11;CNT[12][11][2]=165;CNT[12][11][3]=462;CNT[12][11][4]=330;CNT[12][11][5]=55;CNT[12][11][6]=1;
本文来自博客园,作者:myee,转载请注明原文链接:https://www.cnblogs.com/myee/p/Luogu-solution-cf1671f.html