[hdu7200]Yet Another Easy Permutation Count Problem

令$x_{i}=\sum_{j=1}^{i-1}[P_{i}<P_{j}]$,则$x_{i}\in [0,i)$与$\{P_{i}\}$构成双射

在此基础上,每轮冒泡排序即将所有$x_{i}>0$的位置均减$1$并左移$1$位

$i$为好位置$\iff x_{i}=0<x_{i+1}$,结合前者每个$i$的贡献为$\max(x_{i+1}-x_{i},0)$

显然$x_{i}<x_{i+1}\iff P_{i}>P_{i+1}$,并代入$x_{i}$的式子,贡献也即$\sum_{j=1}^{i}[P_{j}\in (P_{i+1},P_{i}]]$

将贡献式拆开,对三个变量是否确定分类讨论,并特判$i=j$的情况即可

可以用树状数组维护,时间复杂度为$o(n\log n)$,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 1000005
 4 #define mod 998244353
 5 #define ll long long
 6 #define lowbit(k) (k&(-k))
 7 int t,n,m,x,y,cnt,Cnt,ans,fac[N],a[N],sum[N];
 8 int C(int n){
 9     return (ll)n*(n-1)/2%mod;
10 }
11 int C3(int n){
12     return (ll)n*(n-1)%mod*(n-2)%mod*(mod+1)/6%mod;
13 }
14 struct TA{
15     int f[N];
16     void clear(){
17         for(int i=1;i<=n;i++)f[i]=0;
18     }
19     void update(int k,int x){
20         while (k<=n)f[k]=(f[k]+x)%mod,k+=lowbit(k);
21     }
22     int query(int k){
23         int ans=0;
24         while (k)ans=(ans+f[k])%mod,k^=lowbit(k);
25         return ans;
26     }
27     int query(int l,int r){
28         return (query(r)-query(l)+mod)%mod;
29     }
30 }f1,f2,f3;
31 int main(){
32     fac[0]=1;
33     for(int i=1;i<N;i++)fac[i]=(ll)fac[i-1]*i%mod;
34     scanf("%d",&t);
35     while (t--){
36         scanf("%d%d",&n,&m);
37         for(int i=1;i<=n;i++)a[i]=sum[i]=0;
38         for(int i=1;i<=m;i++){
39             scanf("%d%d",&x,&y);
40             a[x]=y,sum[y]=1;
41         }
42         for(int i=1;i<=n;i++)sum[i]=(sum[i]^1)+sum[i-1];
43         m=sum[n],cnt=Cnt=ans=0,f1.clear(),f2.clear(),f3.clear();
44         for(int i=1;i<n;i++){
45             if ((a[i])&&(a[i+1])){
46                 if (a[i]>a[i+1]){
47                     ans=(ans+(ll)fac[m]*(1+f1.query(a[i+1],a[i])))%mod;
48                     if (cnt)ans=(ans+(ll)cnt*fac[m-1]%mod*(sum[a[i]]-sum[a[i+1]]))%mod;
49                 }
50             }
51             if ((a[i])&&(!a[i+1])){
52                 ans=(ans+(ll)fac[m-1]*(sum[a[i]]+f2.query(a[i])))%mod;
53                 if (cnt)ans=(ans+(ll)cnt*fac[m-2]%mod*C(sum[a[i]]))%mod;
54             }
55             if ((!a[i])&&(a[i+1])){
56                 ans=(ans+(ll)fac[m-1]*((m-sum[a[i+1]])+f3.query(a[i+1],n)))%mod;
57                 if (cnt)ans=(ans+(ll)cnt*fac[m-2]%mod*C(m-sum[a[i+1]]))%mod;
58             }
59             if ((!a[i])&&(!a[i+1])){
60                 ans=(ans+(ll)fac[m-2]*(C(m)+Cnt))%mod;
61                 if (cnt)ans=(ans+(ll)cnt*fac[m-3]%mod*C3(m))%mod;
62             }
63             if (!a[i])cnt++;
64             else{
65                 Cnt=(Cnt+(ll)sum[a[i]]*(m-sum[a[i]]))%mod;
66                 f1.update(a[i],1),f2.update(a[i],sum[a[i]]),f3.update(a[i],m-sum[a[i]]);
67             }
68         }
69         printf("%d\n",ans);
70     }
71     return 0;
72 }
View Code

 

posted @ 2022-08-07 15:10  PYWBKTDA  阅读(87)  评论(0编辑  收藏  举报