比赛题。懒得写crt而丢暴力。
问$n \leq 300000$的数列的字典序,$mod \ \ m$,不保证$m$是质数,数列$\leq 300000$,有重复。
虽然说这种强行套两个知识的题目很令人厌恶,但征服他们才是我们厌恶的资本。
首先$p_i$表示数列第$i$个数,$c_i$表示值为$i$有多少个,$t$表示所有数字的最大值,我们要求的是$1+\sum_{i=1}^{n} \sum_{j=1}^{p_i-1} \frac{(n-i)!}{(c_j-1) \prod_{k=1}^{t}[k \neq j]c_k}$。
上下同乘$c_j$,得,等会!!!!!严肃注意,在这里同乘$c_j$,若$c_j=0$则会出现奇怪错误!!所以在式子转化的过程中千万记得,把条件写上去。在这卡了1.5h。
$\sum_{i=1}^{n} \frac{(n-i)!}{\prod_{k=1}^{t}c_k}\sum_{j=1}^{p_i-1}c_j(这坨东西不为0)$.
好的!由于$c$会变,后面那坨用树状数组解决,而那个分式需要对$m$取$mod$,不方便,就把$m$分解完,$m=\sum_{i=1}^{k}a_i^{b_i}$,枚举每个$a_i^{b_i}$做膜数,用欧拉定理求逆元,把质因子$a_i$计指数单独拿出来算。最后用中国剩余定理合并。
1 //#include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 //#include<time.h> 6 //#include<complex> 7 #include<algorithm> 8 #include<stdlib.h> 9 using namespace std; 10 11 int n,mod; 12 #define maxn 300011 13 int cnt[maxn],pp[maxn],a[maxn]; 14 struct BIT 15 { 16 int a[maxn],n; 17 void clear(int m) {n=m;} 18 void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]+=v;} 19 int query(int x) {int ans=0; for (;x;x-=x&-x) ans+=a[x]; return ans;} 20 }t; 21 22 int powmod(int a,int b,int mod) 23 { 24 int ans=1; 25 while (b) 26 { 27 if (b&1) ans=1ll*ans*a%mod; 28 a=1ll*a*a%mod; b>>=1; 29 } 30 return ans; 31 } 32 33 int mm[maxn],ci[maxn],phi[maxn],mi[maxn],num[maxn],ln; 34 void dec() 35 { 36 int tmp=mod; ln=0; 37 for (int i=2;1ll*i*i<=tmp;i++) if (tmp%i==0) 38 { 39 num[++ln]=i; mi[ln]=1; 40 while (tmp%i==0) tmp/=i,mi[ln]*=i; 41 } 42 if (tmp>1) num[++ln]=tmp,mi[ln]=tmp; 43 for (int i=1;i<=ln;i++) phi[i]=mi[i]-mi[i]/num[i]; 44 } 45 46 int xx[maxn]; 47 int china() 48 { 49 int ans=0; 50 for (int i=1;i<=ln;i++) 51 { 52 int w=mod/mi[i],ni=powmod(w,phi[i]-1,mi[i]); 53 ans=(ans+1ll*w*ni%mod*xx[i])%mod; 54 } 55 return ans; 56 } 57 58 int main() 59 { 60 scanf("%d%d",&n,&mod); int Max=0; 61 for (int i=1;i<=n;i++) scanf("%d",&a[i]),cnt[a[i]]++,Max=max(Max,a[i]); 62 t.clear(Max); 63 dec(); 64 for (int j=1;j<=ln;j++) 65 { 66 mm[j]=1; 67 for (int tmp=1;1ll*tmp*num[j]<=n;tmp*=num[j]) ci[j]+=n/(tmp*num[j]); 68 for (int i=1;i<=n;i++) 69 { 70 int tmp=i; while (tmp%num[j]==0) tmp/=num[j]; 71 mm[j]=1ll*mm[j]*tmp%mi[j]; 72 } 73 for (int i=1;i<=Max;i++) 74 { 75 for (int k=1;1ll*k*num[j]<=cnt[i];k*=num[j]) ci[j]-=cnt[i]/(k*num[j]); 76 for (int k=1;k<=cnt[i];k++) 77 { 78 int tmp=k; while (tmp%num[j]==0) tmp/=num[j]; 79 mm[j]=1ll*mm[j]*powmod(tmp,phi[j]-1,mi[j])%mi[j]; 80 } 81 } 82 } 83 for (int i=1;i<=Max;i++) if (cnt[i]) t.add(i,cnt[i]); 84 for (int i=1;i<=n;i++) 85 { 86 int nowt=t.query(a[i]-1); 87 for (int j=1;j<=ln;j++) 88 { 89 int tmp=n-i+1; 90 while (tmp%num[j]==0) ci[j]--,tmp/=num[j]; 91 mm[j]=1ll*mm[j]*powmod(tmp,phi[j]-1,mi[j])%mi[j]; 92 if (nowt) xx[j]=(xx[j]+mm[j]*1ll*powmod(num[j],ci[j],mi[j])%mi[j]*nowt)%mi[j]; 93 tmp=cnt[a[i]]; 94 while (tmp%num[j]==0) ci[j]++,tmp/=num[j]; 95 mm[j]=1ll*mm[j]*tmp%mi[j]; 96 } 97 cnt[a[i]]--; t.add(a[i],-1); 98 } 99 printf("%d\n",(china()+1)%mod); 100 return 0; 101 }