nflsoj 20034 #12429. 「NOIP2021模拟赛0915长郡」仪式感

时间:2021-09-20
本文章向大家介绍nflsoj 20034 #12429. 「NOIP2021模拟赛0915长郡」仪式感,主要包括nflsoj 20034 #12429. 「NOIP2021模拟赛0915长郡」仪式感使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

小 L 喜欢仪式感。小 F 喜欢集合。小 L 喜欢有仪式感的集合。定义一个集合 \(S\) 的仪式感为 \(k\) ,当且仅当S中的所有元素的最大公约数恰好为 \(k\) . 现在小F有一个大小为 \(n\) 的集合 \(S\) ,小 L 想请你对于 \(\forall k\in [1,m]\) ,分别求出 \(\min\{|S_0|\}(S_0\in A)\)\(\max\{S_0\}(S_0\in A)\),其中 \(A\)\(S\) 的所有仪式感为 \(k\) 的非空子集组成的集合。即意,分别求出最少/最多能从 \(A\) 中取出多少个数,使它们的 \(gcd=k\)

\(1\leq n,m\leq 3\times 10^5,m<\max(S_i)\)

简化版本是 cf1043f .

最小值是可以枚举的,那么,如果对于一个 \(1\leq k\leq m\) ,如果存在最小值,那么最大值就是所有包含 \(k\) 为因数的数的个数.

时间复杂度 : \(O(n\log n)\)

空间复杂度 : \(O(n)\)

code

#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
inline int read(){
   char ch=getchar();
   while(ch<'0'||ch>'9')ch=getchar();
   int res=0;
   while(ch>='0'&&ch<='9'){
   	res=res*10+ch-'0';
   	ch=getchar();
   }
   return res;
}
inline void print(int res){
   if(res==0){
   	putchar('0');
   	return;
   }
   int a[10],len=0;
   while(res>0){
   	a[len++]=res%10;
   	res/=10;
   }
   for(int i=len-1;i>=0;i--)
   	putchar(a[i]+'0');
}
const int inf=1e9+10;
int n,m;
int a[300010];
int cnt[300010];
class num{
public:
   int mod;
   int f[300010];
   int c[300010][10];
   void build(){
   	memset(c,0,sizeof(c));
   	c[0][0]=1;
   	for(int i=1;i<300010;i++){
   		c[i][0]=1;
   		for(int j=1;j<=min(i,9);j++){
   			c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
   		}
   	}
   }
   
}h1,h2;
vector<int>v[300010];
int mn[300010],mx[300010];
void work(){
   for(int i=1;i<=300000;i++){
   	for(int j=i;j<=300000;j+=i){
   		v[j].push_back(i);
   	}
   }
}
void get_cnt(int val){
   for(int i=0;i<(int)v[val].size();i++){
   	cnt[v[val][i]]++;
   }
}
int main(){
//	freopen("sor.in","r",stdin);
//	freopen("sor.out","w",stdout);
   h1.mod=998244353;
   h2.mod=1000000007;
   h1.build();
   h2.build();
   work();
//	cout<<"ok"<<endl;
   n=read();m=read();
   for(int i=0;i<n;i++)a[i]=read();
   for(int i=0;i<n;i++)get_cnt(a[i]);	
//	for(int i=1;i<=10;i++)cout<<cnt[i]<<" ";
//	cout<<endl;
   for(int i=0;i<300010;i++)mn[i]=inf;
   for(int i=0;i<300010;i++)mx[i]=-inf;
   for(int t=1;t<10;t++){
   	memset(h1.f,0,sizeof(h1.f));
   	memset(h2.f,0,sizeof(h2.f));
   	for(int i=300000;i>=1;i--){
   		h1.f[i]=h1.c[cnt[i]][t];
   		h2.f[i]=h2.c[cnt[i]][t];
   		for(int j=i*2;j<=300000;j+=i){
   			h1.f[i]=(h1.f[i]-h1.f[j]+h1.mod)%h1.mod;
   			h2.f[i]=(h2.f[i]-h2.f[j]+h2.mod)%h2.mod;
   		}
   	//	if(h1.f[i]!=0||h2.f[i]!=0)cout<<i<<","<<h1.f[i]<<","<<h2.f[i]<<" ";
   		if(h1.f[i]!=0||h2.f[i]!=0){
   			mn[i]=min(mn[i],t);
   			mx[i]=max(mx[i],cnt[i]);
   		}
   	}
   }
   for(int i=1;i<=m;i++){
   	if(mn[i]==inf){
   		putchar('-');
   		putchar('1');
   	}
   	else{
   		print(mn[i]);
   	}
   	putchar(' ');
   	if(mx[i]==-inf){
   		putchar('-');
   		putchar('1');
   	}
   	else{
   		print(mx[i]);
   	}
   	putchar('\n');
   }
   return 0;
}
/*inline? ll or int? size? min max?*/
/*
7 5
30 60 21 42 70 15 30
*/
/*
3 6
2 4 6
*/

原文地址:https://www.cnblogs.com/suadwm/p/15314191.html