P6022ハッピーウォーター問題ソリューション

CSDN同期

元のタイトルリンク

簡単なタイトル:最初は幸せな水のボトル\(n \)本あり、\(1 \)の幸せな水のボトルごとに\(n \)個のオブジェクトをアタッチでき、最初の\(i \)オブジェクトには\( a_iを\)一つができ、その後取得\(1 \)水の楽しみのボトルを借用/クレジット、許可された幸せな水のボトルの最大数を見つけることは許可されていません。無制限の場合は、\(\ text {Inf} \)を出力します

Luo Gu \(T1 \)に対する毎月の質問です

とりあえず、ゲーム中はあまり考えませんでした。当時は、\(T1 \)は水のシミュレーションだと思っていましたが、慎重に考えました:\(m = 5 \)デッドループがリングに引っかかったらどうなるでしょうか。場合は\({Infを} \ \テキスト ) ケース文が出てこないが、どのようにしますか?行き詰まった場合はどうすればよいですか\(\ text {TLE} \)

しかし、私は慌てることなく、1つずつ解決することにしました。

しかし、本当の意味での現実シミュレーションでは、一種のある表情あまりにも無謀に、直接出て、水の問題をシミュレートすることであるのではなく、思考が一定量解決するために別のシミュレーションを通じて知ることができるこのタイトルのは、オレンジ色のタイトルはすべきではないと名付けられましたはい、そうであってはなりません。

無限ループがリングに巻き込まれる問題が最も困難です。しかし、慎重に考えて:すべてのあなたが幸せにボトルを取得数は増加し、より多くの、いくつかのケースでは存在しませんでした。終わりを判断するには?幸福な水は得られず、終わってしまいます。

それで、無限の状況をどのように判断するのですか?明らかに、無限の場合に限り、すべての\(a_iを\)に等しくかつ(a_iを\ n型のLeq \)\なぜ?なぜなら、すべての場合\(a_iを\)等しく、最初の単語が最初に誘導され得る各動作後\(a_iを\)等しく、各派生\(M \)メトロポリタン再生成し、再生成\(\ cdots \ cdots \)制限がないため、サンプルが理解できない場合は、サンプルを見ることができます。

これがすべて解決された後、\(\ text {TLE} \)問題に対して何をすべきですか?

しかし、考えてみれば、本当に\(\ text {TLE} \)になりますか?

ローンと返済の数を最大化するには、一連のデータを作成する必要があります。

ここで、素晴らしく優れた\(\ text {WYXkk} \)質問者が、\(\ text {hack} \)データのすばらしいセットを提供しました。

10000 5
2 3 7 43 1807

構築方法は、\(a_i = \ Big(\ prod_ {j = 1} ^ {i-1} a_j \ Big)+ 1 \)、および\(a_i = 2 \)です。

実際の測定後、このデータは\(2.8 \回10 ^ 7 \)回に達します!(答えは\(3 \×10 ^ {10} \)に達し、部分的に開く必要があります\(\ text {long long} \)

もちろん、\(m = 6 \)シミュレーションがそれを解決できない場合。

時間の複雑さ:\(O(\ text {wys})\)。(おそらく非常に良い)

実際のスコア:\(100pts \)

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;

inline int read(){char ch=getchar();int f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
	int x=0;while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();return x*f;}

int n,m; long long ans=0;
int a[6],b[6],c[6];

long long l;
bool x=0; //无限情况
inline void check(){
	for(int i=1;i<=m;i++)
		if(b[i]>=a[i]) l+=b[i]/a[i],b[i]%=a[i];
} //当前瓶数为 b , a 是初始数组 , l 记录多出来的瓶数

int main(){
	n=read(),m=read();
	for(int i=1;i<=m;i++) a[i]=read(),b[i]=n;
	ans+=n;
	while(1) {
		for(int i=1;i<=m;i++) c[i]=b[i];
		l=0; check();
		if(!l) break;
		ans+=l;
		for(int i=1;i<=m;i++) b[i]+=l; //记录答案,重新衍生
		bool f=0;
		for(int i=1;i<=m;i++) if(c[i]-b[i]) {f=1;break;} //做标记
		if(!f) {x=1;break;} //如果 c[i] = b[i] 则说明一次之后根本没变 , 是无限情况
	}
	if(x) printf("Inf"); else
	printf("%lld\n",ans);
	return 0;
}

おすすめ

転載: www.cnblogs.com/bifanwen/p/12727720.html