【xsy2815】净空 大暴力

绝了场上居然没做这一题

题目大意:给你一个数$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\n",cnt);
50     for(int i=1;i<=cnt;i++) printf("%d %d\n",ansx[i],ansy[i]);
51 }
扫描二维码关注公众号,回复: 5584056 查看本文章

猜你喜欢

转载自www.cnblogs.com/xiefengze1/p/10556419.html