BZOJ1129: [POI2008]Per

Posted Blue233333

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1129: [POI2008]Per相关的知识,希望对你有一定的参考价值。

比赛题。懒得写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 }
View Code

 

以上是关于BZOJ1129: [POI2008]Per的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1131: [POI2008]Sta

bzoj1113[Poi2008]海报PLA*

BZOJ1123: [POI2008]BLO

BZOJ1131: [POI2008]Sta

[bzoj1116][POI2008][CLO]

BZOJ 1124[POI2008]枪战