题目链接 gym101778
Problem A
转化成绝对值之后算一下概率。这个题有点像 2018 ZOJ Monthly March Problem D ? 不过那个题要难一些~
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define MP make_pair
#define fi first
#define se second
typedef long long LL;
const LL mod = 1e9 + 7;
const int N = 2e5 + 10;
int T;
int n, m;
LL fac[N];
inline LL Pow(LL a, LL b, LL mod){
LL ret(1);
for (; b; b >>= 1, (a *= a) %= mod) if (b & 1) (ret *= a) %= mod;
return ret;
}
inline LL C(LL n, LL m){ return m > n ? 0 : fac[n] * Pow(fac[m] * fac[n - m] % mod, mod - 2, mod) % mod; }
int main(){
fac[0] = 1;
rep(i, 1, 2e5 + 1) fac[i] = fac[i - 1] * 1ll * i % mod;
scanf("%d", &T);
while (T--){
scanf("%d%d", &n, &m);
n = abs(n);
if (n == 0 && m == 0){
puts("1");
continue;
}
if (m < n){
puts("0");
continue;
}
if ((m + n) % 2 == 1){
puts("0");
continue;
}
int x = (m + n) / 2;
printf("%lld
", C(m, x) * Pow(Pow(2, m, mod), mod - 2, mod) % mod);
}
return 0;
}
Problem B
把首项定成$1$然后二分答案就可以了
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define MP make_pair
#define fi first
#define se second
typedef long long LL;
int T;
LL n, a, l, r, t;
int main(){
scanf("%d", &T);
while (T--){
scanf("%lld%lld", &n, &a);
l = 0, r = n;
while (l + 1 < r){
LL mid = (l + r) >> 1;
if (mid * (mid + 1) / 2ll <= n * a - n + mid) l = mid;
else r = mid - 1;
}
if (r * (r + 1) / 2ll <= n * a - n + r) t = r;
else t = l;
printf("%lld
", t);
}
return 0;
}
Problem C
找规律。$ans = (n - 1) * phi(n)$
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
typedef long long LL;
const int N = 1e6 + 10;
int T;
int phi[N];
int n;
int main(){
rep(i, 2, 1e6 + 1){
if (!phi[i]){
for (int j = i; j <= 1e6; j += i){
if (!phi[j]) phi[j] = j;
phi[j] -= phi[j] / i;
}
}
}
scanf("%d", &T);
while (T--){
scanf("%d", &n);
printf("%lld
", 1ll * (n - 1) * phi[n]);
}
return 0;
}
Problem D
状态压缩,对于每一个集合求MST
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
const int N = 16;
int T;
int n, m, k;
int a[N][N], c[1 << N];
int all;
int ans;
int main(){
scanf("%d", &T);
while (T--){
scanf("%d%d%d", &n, &m, &k);
memset(c, 0, sizeof c);
memset(a, -1, sizeof a);
ans = 2e9;
rep(i, 1, m){
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
--x;
--y;
a[x][y] = a[y][x] = z;
}
all = 0;
rep(i, 1, k){
int x;
scanf("%d", &x);
--x;
all |= (1 << x);
}
int mx = (1 << n) - 1;
rep(i, 1, mx){
c[i] = 2e9;
int p = 0;
dec(j, n - 1, 0) if ((i >> j) & 1){
p = j;
break;
}
if ((i ^ (1 << p)) == 0){
c[i] = 0;
continue;
}
dec(j, n - 1, 0){
if ((i >> j) & 1){
rep(k, 0, n - 1){
if (((i >> k) & 1) && (j != k) && (~a[j][k])) c[i] = min(c[i], c[i ^ (1 << j)] + a[j][k]);
}
}
}
}
rep(i, 1, mx) if ((i & all) == all) ans = min(ans, c[i]);
printf("%d
", ans);
}
return 0;
}
Problem E
直接模拟
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define fi first
#define se second
#define MP make_pair
typedef long long LL;
int T;
int n, x, y;
int id, d, m;
int mxd, mxm;
int main(){
scanf("%d", &T);
while (T--){
scanf("%d%d%d", &n, &x, &y);
mxd = 1e9, mxm = 0;
id = -1;
rep(i, 1, n){
scanf("%d%d", &d, &m);
if (d <= x && m >= y){
if (mxd > d || (mxd == d && mxm < m)){
mxd = d;
mxm = m;
id = i;
}
}
}
printf("%d
", id);
}
return 0;
}
Problem F
这个题略卡常数。
对每个权值求二维前缀和,二分答案就好了。
#include <bits/stdc++.h>
namespace IO{
const int MT = 20 * 1024 * 1024;
char IO_BUF[MT];
int IO_PTR, IO_SZ;
void begin(){
IO_PTR = 0;
IO_SZ = fread (IO_BUF, 1, MT, stdin);
}
template<typename T>
inline bool scan_d (T & t){
while (IO_PTR < IO_SZ && IO_BUF[IO_PTR] != '-' && (IO_BUF[IO_PTR] < '0' || IO_BUF[IO_PTR] > '9'))IO_PTR ++;
if (IO_PTR >= IO_SZ) return false;
bool sgn = false;
if (IO_BUF[IO_PTR] == '-') sgn = true, IO_PTR ++;
for (t = 0; IO_PTR < IO_SZ && '0' <= IO_BUF[IO_PTR] && IO_BUF[IO_PTR] <= '9'; IO_PTR ++)
t = t * 10 + IO_BUF[IO_PTR] - '0';
if (sgn) t = -t;
return true;
}
};
using namespace IO;
using namespace std;
#define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define MP make_pair
#define fi first
#define se second
typedef long long LL;
const int M = 503;
const int N = 1e2 + 2;
int c[M][N][N];
int a[N][N];
int n, m, q;
int mx;
int T;
int calc(int x1, int y1, int x2, int y2, int val){
return c[val][x2][y2] - c[val][x2][y1 - 1] - c[val][x1 - 1][y2] + c[val][x1 - 1][y1 - 1];
}
void print(int x){
if (x > 9) print(x / 10);
putchar(x % 10 + '0');
}
int main(){
begin();
scan_d(T);;
while (T--){
scan_d(n);
scan_d(m);
scan_d(q);
mx = 0;
rep(i, 1, n){
rep(j, 1, m) scan_d(a[i][j]), mx = max(mx, a[i][j]);
}
rep(k, 0, mx){
rep(i, 0, n + 1){
rep(j, 0, m + 1) c[k][i][j] = 0;
}
}
rep(k, 1, mx){
rep(i, 1, n){
rep(j, 1, m){
c[k][i][j] = c[k][i - 1][j] + c[k][i][j - 1] - c[k][i - 1][j - 1] + (a[i][j] <= k);
}
}
}
while (q--){
int x1, y1, x2, y2;
scan_d(x1);
scan_d(y1);
scan_d(x2);
scan_d(y2);
int all = (x2 - x1 + 1) * (y2 - y1 + 1);
all = (all + 1) / 2;
int l = 1, r = mx;
while (l + 1 < r){
int mid = (l + r) >> 1;
if (calc(x1, y1, x2, y2, mid) >= all) r = mid;
else l = mid + 1;
}
int t;
if (calc(x1, y1, x2, y2, l) >= all) t = l;
else t = r;
print(t);
putchar(10);
}
}
return 0;
}
Problem G
根据割线定理来做。
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define fi first
#define se second
#define MP make_pair
typedef long long LL;
int T;
int n, x, y;
int id, d, m;
int mxd, mxm;
int main(){
scanf("%d", &T);
while (T--){
scanf("%d%d%d", &n, &x, &y);
mxd = 1e9, mxm = 0;
id = -1;
rep(i, 1, n){
scanf("%d%d", &d, &m);
if (d <= x && m >= y){
if (mxd > d || (mxd == d && mxm < m)){
mxd = d;
mxm = m;
id = i;
}
}
}
printf("%d
", id);
}
return 0;
}
Problem H
假的数据结构……其实还是模拟
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define MP make_pair
#define fi first
#define se second
typedef long long LL;
const int N = 1e5 + 10;
int T;
int n, m;
char s[N], ch[2];
int main(){
scanf("%d", &T);
while (T--){
scanf("%d%d", &n, &m);
scanf("%s", s + 1);
int c = 0;
rep(i, 1, (n + 1) >> 1) if (s[i] == s[n - i + 1]) ++c;
int all = (n + 1) >> 1;
int ans = 0;
while (m--){
int x;
scanf("%d%s", &x, ch);
if (s[x] == s[n - x + 1]){
s[x] = ch[0];
if (s[x] != s[n - x + 1]) --c;
}
else{
s[x] = ch[0];
if (s[x] == s[n - x + 1]) ++c;
}
if (c == all) ++ans;
}
printf("%d
", ans);
}
return 0;
}
Problem I
签到
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define MP make_pair
#define fi first
#define se second
typedef long long LL;
int T;
int main(){
scanf("%d", &T);
while (T--){
int a, b, c, d;
scanf("%d%d%d%d", &a, &b, &c, &d);
if (a == d && b == c){
puts("-1");
continue;
}
if (a + c == b + d){
if (c > a) puts("1"); else puts("2");
}
else if (a + c > b + d) puts("1");
else puts("2");
}
return 0;
}
Problem J
挺有意思的一个题。
其实暴力做就可以了。因为在1e9的范围内质数间隔最大大概只有$320$。
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
typedef long long LL;
int T;
int fg;
LL l, r;
bool check(LL x){
if (x <= 10) return false;
string s1 = "";
for (; x; x /= 10) s1 += x % 10 + '0';
reverse(s1.begin(), s1.end());
int n = s1.length();
string s2 = s1.substr(0, (n + 1) / 2);
string s3 = s1.substr((n + 1) / 2);
LL a = 0, b = 0;
for (auto u : s2) a = a * 10 + u - '0';
for (auto u : s3) b = b * 10 + u - '0';
return __gcd(a, b) == 1;
}
int main(){
scanf("%d", &T);
while (T--){
scanf("%lld%lld", &l, &r);
fg = 0;
for (LL i = r; i >= l; --i){
if (check(i)){
fg = 1;
printf("%lld
", i);
break;
}
}
if (!fg) puts("-1");
}
return 0;
}
Problem K
模拟……
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define MP make_pair
#define fi first
#define se second
typedef long long LL;
struct state{
int x, y, z, t;
state(){
x = y = z = t = -1;
}
state(int x, int y, int z, int t) :
x(x), y(y), z(z), t(t){
}
bool operator < (const state &e) const{
return t < e.t;
}
};
const int N = 1e2 + 2;
int T;
int n, m, k;
int fb[N];
int WA[N][N], FAC[N];
vector <state> sub;
int main(){
scanf("%d", &T);
while (T--){
scanf("%d%d%d", &n, &m, &k);
int x, y, z, tm, ts;
sub.clear();
rep(i, 0, k - 1){
scanf("%d%d%d%d:%d", &x, &y, &z, &tm, &ts);
sub.push_back(state(x - 1, y - 1, z, tm * 60 + ts));
}
sort(sub.begin(), sub.end());
memset(fb, -1, sizeof fb);
memset(WA, 0, sizeof WA);
memset(FAC, 0, sizeof FAC);
int ep = -1, sg = -1;
pair<int, int> sp(-1, 0), rp(-1, 0);
rep(i, 0, k - 1){
if (sub[i].z == 0)
++WA[sub[i].x][sub[i].y];
else{
if (fb[sub[i].x] == -1)
fb[sub[i].x] = sub[i].y + 1;
if (ep == -1)
ep = sub[i].y + 1;
sg = sub[i].y + 1;
if (WA[sub[i].x][sub[i].y] == 0)
++FAC[sub[i].y];
if (FAC[sub[i].y] > sp.first || (FAC[sub[i].y] == sp.first && sub[i].y + 1 < sp.second))
sp = make_pair(FAC[sub[i].y], sub[i].y + 1);
if (WA[sub[i].x][sub[i].y] > rp.first || (WA[sub[i].x][sub[i].y] == rp.first && sub[i].y + 1 < rp.second))
rp = make_pair(WA[sub[i].x][sub[i].y], sub[i].y + 1);
}
}
rep(i, 0, n - 1) printf("%s%d", i ? " " : "", fb[i]);
putchar(10);
printf("%d %d %d %d
", ep, sg, sp.se, rp.se);
}
return 0;
}