補充リンク:2019マルチ3コンテスト東京大学トレーニング
1002街を爆破(HDU-6604)
問題の意味
所与\(N- \)点と\(m個\)エッジが非巡回グラフが与えられ向けた\(Q \)回の問い合わせ、各質問所与\(\)と\(B \)、ポイントの数を見つけ、ポイントが削除後満たす\(\)と\(B \)を少なくとも1つの点にする度に達していない\(0 \)ポイント。
問題の解決策
ドミネーターツリー/絶滅最近の共通の祖先のツリートポロジーソート
1006 Fansblog (HDU-6608)
問題の意味
所与プライム\(\ P(1E ^ 9 \のLeq P \のLeq 1E ^ {14})\)未満見つけよう\(P \)素数の最大数\(\ Q \) 、取得\(\ Qを!\ MOD \ P \) 。
問題の解決策
ウィルソンの定理の素数の密度分布逆ミラー・ラビンテスト素数
ウィルソンの定理:場合にのみ\(P \)とき素数:\((P - 1)\当量-1 \ MOD \ P \!。)
それ\((P-1)\当量(P-1)\ MOD \ P \!。。)以来、\((P - !! 1 )=(Q)*(Q + 1)*(Q + 2)* * ...(P - 1)\) 、利用可能な\(Q \ MOD \ P = \ FRAC {(P! - 1)} {(Q + 1)*(Q + 2)* ... *( P - 1)} \ MOD \ P = \ FRAC {1} {(Q + 1)*(Q + 2)* ... *(P - 2)} \ MOD \ P \)
使用することができる\(ミラーラビン\)試験は素数試験部門として使用されてもよい、素数を決定しました。
超えない素数の間隔\(600 \) (大きな素数BETWEENプライム(GAPS)の間に大きな間隔)とから従って直接入手できる( - 1 \ P)\検索(Q \)を\。
大きな数は、急速に乗算する必要があることに注意してください。(WAいくつかの髪)
コード:
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
ll mulmod(ll a, ll b, ll m) {
ll ans = 0;
while (b) {
if (b & 1) ans = (ans + a) % m;
a = (a << 1) % m;
b >>= 1;
}
return ans % m;
}
ll qmod(ll a, ll b, ll m) {
if(!b) return 1 % m;
ll ans = 1;
while (b) {
if (b & 1) ans = mulmod(ans, a, m);
a = mulmod(a, a, m);
b >>= 1;
}
return ans % m;
}
bool Miller_Rabbin(ll n, ll a) {
ll d = n - 1, s = 0, i;
while (!(d & 1)) {
d >>= 1;
s++;
}
ll t = qmod(a, d, n);
if (t == 1 || t == -1)
return 1;
for (i = 0; i < s; i++) {
if (t == n - 1)
return 1;
t = mulmod(t, t, n);
}
return 0;
}
bool is_prime(ll n) {
ll i, tab[4] = {3, 4, 7, 11};
for (i = 0; i < 4; i++) {
if (n == tab[i])
return 1;
if (!n % tab[i])
return 0;
if (n > tab[i] && !Miller_Rabbin(n, tab[i]))
return 0;
}
return 1;
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
ll n;
scanf("%lld", &n);
for (ll i = n - 1;; --i) {
if (is_prime(i)) {
ll ans = 1;
for (ll j = i + 1; j <= n - 2; ++j) {
ans = mulmod(ans, qmod(j, n - 2, n), n);
}
ans = (ans + n) % n;
printf("%lld\n", ans);
break;
}
}
}
return 0;
}
1007年の答えを探す(HDU-6609)
問題の意味
所与\(N- \)整数\(W_i(iは1 \当量当量nを\)\) と整数\(Mの\) 、それぞれのための\(\ I(1 \当量 iが当量nを\)\) 、削除するために必要な最小数を見つける\(W_kを(1 \のLeq K <I)\)、そう\(\ sum_ 1} = {J ^ iW_j \のLeq Mが\) 。前記\(1 \当量W_i \当量の M(1 \当量iは当量nを\)\)
問題の解決策
マルチセットSTL
妖精の練習
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
multiset<int> s;
ll a[maxn];
int main() {
int T;
scanf("%d", &T);
while(T--) {
int n; ll m;
s.clear();
scanf("%d %lld", &n, &m);
for(int i = 1; i <= n; ++i) {
scanf("%lld", &a[i]);
}
ll sum = 0;
int res = 0;
for(int i = 1; i <= n; ++i) {
int cnt = 0;
ll tmp = sum;
if(tmp + a[i] > m) {
auto it = s.end();
while(tmp + a[i] > m) {
--it;
tmp -= *it;
++cnt;
}
}
printf("%d ",cnt + res);
s.insert(a[i]);
sum += a[i];
auto it = s.end();
while(sum > m) {
--it;
sum -= *it;
s.erase(s.find(*it));
++res;
}
}
printf("\n");
}
return 0;
}