BZOJ 3181: [Coci2012]BROJ 【數據分治(暴力+(二分&&容斥))

根據數據範圍猜解法,數據分治!!!【x

好吧……其實是先想到了容斥的,然而容斥姿勢不太好果斷GG沒寫,反正覺得容斥的話p肯定不能太大,然後又yy了循環節啥的各種鬼畜東西233333(雖然最後發現根本沒什麼卵用

然後在考試結束前幾分鐘被小朋友嘲諷,忽然就想到了怎麼寫p比較大的,在線性篩的時候,順手記錄每個數的最小質因子,因爲p大,所以p的係數應該是很小的,於是直接枚舉,如果枚舉到的數的最小質因子大於等於p就++cnt,最後cnt==n的時候break

容斥的時候可以用dfs,乘上當前的數如果比n大就直接continue,剪了一堆枝


我應該是寫掛了…………反正數據水23333

#include<bits/stdc++.h>
#define INF 1000000000
#define MAXN 2000005
using namespace std;	int n,p;
int tag[MAXN] , prime[MAXN];

void get_prime(int x){
	for(int i=2;i<=x;++i){
		if(!tag[i])	prime[++prime[0]] = i , tag[i] = i;
		for(int j=1;j<=prime[0];++j){
			if(1ll*i*prime[j]>x)	break;
			tag[i*prime[j]] = prime[j];
			if(!(i%prime[j]))	break;
		}
	}
//	for(int i=0;i<=prime[0];++i)	printf("%d\n",prime[i]);
}

int tmp;
void dfs(int x,int pos,int pro,int k){
	if(!pos)	tmp += x/pro *k;
	else{
		dfs(x,pos-1,pro,k);
		if(1ll*pro*prime[pos]<=x)
			dfs(x,pos-1,pro*prime[pos],-k);
	}
}

void sol(){
	get_prime(p);
	int pos = prime[0];
	int l = p*p , r = INF+1;
	while(l^r){
		int mid = (l+r)>>1;
		tmp = 0;
		dfs(mid/p,pos-1,1,1);
		if(tmp<n)	l = mid+1;
		else r = mid;
	}
	printf("%d",l>INF?0:l);
}

int main(){
//	freopen("broj.in","r",stdin);
//	freopen("broj.out","w",stdout);
	
	scanf("%d%d",&n,&p);

	if(n==1)	return printf("%d",p),0;
	
	if(1ll*n*p>INF)	return puts("0"),0;
	
	if(p==2){
		long long ans = 2ll*n;
		printf("%lld",ans>INF?0ll:ans);
		return 0;
	}
	
	if(p>=500){
		get_prime(2000000);
		for(int i=p,j=1;i<=2000000;++i){
			if(tag[i]>=p)	++j;
			if(j==n)
				return printf("%d",1ll*i*p>INF?0:i*p),0;
		}
	}
	else
		sol();
		
	return 0;
}




發佈了123 篇原創文章 · 獲贊 3 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章