[NOIPシミュレーションテスト]:数論(数学)

トピックポータル(内部タイトル11)


入力形式

データ群、整数、および良好な標準範囲の数を表す第1の行、3つの整数の$ T、K、Mの$、。
そして、$ T $ライン、各整数の$ n_iの$、挑戦の代わりに。


出力フォーマット

$のT $出力ライン、$ I $ I $ $問合せ出力の最初の行$の数良い$ n_i整数を表す整数。
答えは$ M $与えられた保証以下であってはなりません。


サンプル

サンプル入力1:

1 0 23333
10

出力例1:

20

サンプル入力2:

3 5 998244353
28
165
233

サンプル出力2:

42
9360
63360


データ範囲とヒント

サンプル1点の説明:

$ 10 $の前に優れた整数は1,2,3,4,6,8,10,12,18,20 $ $です。

データ範囲:

すべてのデータのために、$ 1 \ leqslant T \ leqslant 20.0 \ leqslant K \ leqslant 233,1 \ leqslant n_i \ leqslant Mの\ leqslant {10} ^ {18}。


問題の解決策

$ pが素数の$のために、私たちはたったの$ p個の$素因数セットの$ G $の未満を含むすべての正の整数を考えます。見つけることは困難:
  $ X \でG $、$ G $の場合と整数でKは、$ X $すなわち間違いない良いおよそ$ Xの$、の数よりも数以上の$ X $ $ $小さなを持っています$ XPの^ C(C \ geqslantは 0)$は確かに良いではありません。
我々は大まかなアイデアを得ることができるように。私たちは、たったの$ 1 $が良好であることを考えるようになった、品質係数列挙$ pを$は、オリジナルのそれぞれのためにそれはかなりの数の$ xには$、$ XP ^ cが(C \ geqslantです 0)$ 、その後、候補リストに参加します候補リストは、次の反復を入力して、かなりの数ではないことがすでに決定を削除、並べ替え。かなりの数をするつもりはないが、このアルゴリズムでは、かなりの数の$ xに$を取り除くない、ことを示すのは容易にはかなりの数になり、フォローアップのプロセスではもともとなかった、数を取り除くために良好なプロセスです剪定は合法です。
しかし、品質係数の列挙の範囲にあること?レノボ$ K = 0 $この古典的な問題は、我々は$ 20 $定性的要因を取る、最初の$ ^ {10}、{18} $の範囲のためにので、十分以上であることを知っています大きな質量の添加率は最適ではありません。$ K $の大きなでは、我々は答えは反復の長い期間の後には変更がない場合の答えは変更するかどうかを確認するために、反復の各ラウンドの後に「安定性に反復を」アイデアを使用するとき、私たちは信じているの$ P $の品質係数上限に達しています。練習後、場合$ K = 233 $、$ P $の最大値は、$するために$ 293取られます。
私たちは、繰り返しのかなりの数であると判断しないで削除する方法を検討してください。前$ K + 1 $ $ K + 1 $大きな値よりも$ X $少ない場合には、数の$ xに$の候補リストを列挙するために大に小さな大きな値を維持考えてみましょう、我々は削除この番号を入れます。それ以外の場合は、$ K + 1 $大きな値を更新する前に。上記の説明は、概ね複雑さを推定することができます。$ K = 233 $、$ {設定すると 10} ^ {18} 良い$ $の数Nは$、実践を通して、それは約$ $ $ N $ 50,000が知られている数です。それぞれの剪定が完了した後、$ \ $ M番号ログの拡張機能の数まで拡張し、リストのサイズの$ N $以下に戻ります。

時間の複雑さ:最大(P \ $ \シータ((N \回K \時間が)\ M)$を記録します。

期待はスコア:$ $ 100ポイントを。

実際のスコア:$ $ 100ポイント。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int T,K;
long long M;
int prime[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293};
int cnt,num,size;
pair<int,long long> heap[200000],que[200000],flag[200000];
bool cmp(pair<int,long long> x,pair<int,long long> y){return x.second==y.second?x.first<y.first:x.second<y.second;}
void up(int x)
{
	while(x>1)
		if(heap[x]<heap[x>>1])
		{
			swap(heap[x],heap[x>>1]);
			x>>=1;
		}
		else break;
}
void insert(pair<int,long long> x){heap[++size]=x;up(size);}
void down(int x)
{
	int s=x<<1;
	while(s<=size)
	{
		if(s<size&&heap[s]>heap[s|1])s|=1;
		if(heap[s]<heap[x])
		{
			swap(heap[s],heap[x]);
			x=s;
			s=x<<1;
		}
		else break;
	}
}
void change(pair<int,long long> x){heap[1]=x;down(1);}
int main()
{
	scanf("%d%d%lld",&T,&K,&M);
	que[++cnt]=make_pair(1,1);
	for(int i=0;i<62;i++)
	{
		num=0;
		long long lft=0,rht=M/prime[i],k=0;
		while(lft<=rht)
		{
			lft=max(lft*prime[i],1LL);
			k++;
			for(int j=1;j<=cnt&&lft*que[j].second<=M;j++)
				flag[++num]=make_pair(que[j].first*k,lft*que[j].second);
		}
		sort(flag+1,flag+num+1,cmp);
		int lst=cnt;
		cnt=size=0;
		for(int j=1;j<=min(K+1,num);j++)
		{
			insert(flag[j]);
			que[++cnt]=flag[j];
		}
		for(int j=min(K+1,num)+1;j<=num;j++)
			if(flag[j].first>=heap[1].first)
			{
				change(flag[j]);
				que[++cnt]=flag[j];
			}
		if(lst==cnt)break;
	}
	while(T--)
	{
		int x;
		scanf("%d",&x);
		printf("%lld\n",que[x].second);
	}
	return 0;
}

rp++

おすすめ

転載: www.cnblogs.com/wzc521/p/11367276.html