マイナスゲーム
タイトルリンク:nowcoder 214272
Niu Keへ:
トピック
毎回2つの数字を削除し、これら2つの数字とkの積に変更できるシーケンスがあります。
次に、変換後に残っている最大数を尋ねます。
アイデア
この質問に対する貪欲を考えると、最小の2つの乗算を選択する必要があることがわかります。
次に、ヒープメンテナンスの使用を検討しますが、乗算するとモジュロが発生し、ヒープ内の最小値が実際の最小値ではなくなることがわかります。
では、どうすればよいでしょうか。
次に、最後まで乗算した後、その数はすでに非常に大きく、最小の2を乗算すると、前の最大値よりも大きくなることがわかります。
次に、ヒープ乗算を使用して最初にこの状況に到達することを検討し(最初にモジュラスを取得しない)、次に下のキューを使用して維持し、最初の2つを直接削除して、毎回kkを積に追加しますk。
コード
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define mo 1000000007
using namespace std;
queue <int> qq;
int n, k, ans, maxn;
ll x, y;
priority_queue <int, vector<int>, greater<int> > q;
int main() {
scanf("%d %d", &n, &k);
for (int i = 1; i <= n; i++) {
scanf("%d", &x);
q.push(x);
maxn = max(maxn, (int)x);
}
while (q.size() > 1) {
x = q.top();
q.pop();
y = q.top();
q.pop();
if (x * y + k > maxn) {
//最小的两个乘起来比原来最大的还要大了
q.push(x);
q.push(y);
break;
}
q.push(x * y + k);
}
while (!q.empty()) {
qq.push(q.top());
q.pop();
}
while (qq.size() > 1) {
x = qq.front();
qq.pop();
y = qq.front();
qq.pop();
qq.push(((ll)x * y + k) % mo);
}
printf("%d", qq.front());
return 0;
}