绝了场上居然没做这一题
题目大意:给你一个数$x=Pi_{i=1}^{n}a_i!$。
你需要将x表示为$x=Pi_{i=1}^{m}(c_i!)^{d_i}p$
满足$p$无法再分解,且$(c_1,d_1,c_2,d_2,...,c_m,d_m)$的字典序最大。
数据范围:$1≤n,a_i≤10^5$。
我们考虑预处理出$10^5$内的质数。
读入数列$a$后,我们对数列$a$进行一些处理。令$sum[i]$表示数列$a$中出现了多少个质因子$p[i]$,其中$p[i]$表示第i个质数。
然后,我们从大到小枚举$c_i$,然后再判断$d_i$是否可行。
这么搞复杂度貌似是$O(dfrac{n^2}{ln n})$的,然而实际上它跑得飞快?
1 #include<bits/stdc++.h> 2 #define M 100010 3 #define L long long 4 using namespace std; 5 6 int pri[M]={0},las[M]={0},id[M]={0},use=0; 7 void init(){ 8 for(int i=2;i<M;i++){ 9 if(!las[i]) id[pri[++use]=i]=use,las[i]=1; 10 for(int j=1;j<=use&&i*pri[j]<M;j++){ 11 las[i*pri[j]]=i; 12 if(i%pri[j]==0) break; 13 } 14 } 15 } 16 17 L a[M]={0},sum[M]={0},now[M]={0}; 18 int ansx[M]={0},ansy[M]={0},cnt=0,top=0; 19 bool cmp(){ 20 for(int i=top;i;i--) 21 if(sum[i]<now[i]) return 0; 22 return 1; 23 } 24 25 int main(){ 26 init(); top=use; 27 int n; scanf("%d",&n); 28 for(int i=n,x;i;i--) scanf("%d",&x),a[x]++; 29 for(int i=M-2;i;i--) a[i]+=a[i+1]; 30 for(int i=M-1;i;i--){ 31 for(int j=i;j>1;j=las[j]){ 32 int p=id[j/las[j]]; 33 sum[p]+=a[i],now[p]++; 34 } 35 } 36 for(int i=M-1;i>1;i--){ 37 if(cmp()){ 38 L mns=M; 39 for(int j=top;j;j--) if(now[j]) mns=min(mns,sum[j]/now[j]); 40 for(int j=top;j;j--) sum[j]-=now[j]*mns; 41 cnt++; ansx[cnt]=i; ansy[cnt]=mns; 42 } 43 for(int j=i;j>1;j=las[j]){ 44 int p=id[j/las[j]]; 45 now[p]--; 46 } 47 while(top&&now[top]==0) top--; 48 } 49 printf("%d ",cnt); 50 for(int i=1;i<=cnt;i++) printf("%d %d ",ansx[i],ansy[i]); 51 }