一边监考一边写了几个题。一队出的题目挺好的。总的来说,题目不难,但是坑点比较多,细心点才能做好。
A. Asia区域赛
签到题:
#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))
#define line cout<<"--------------"<<endl
typedef long long ll;
const int maxn = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int main(){
cout << 29+58+87+13 << endl;
return 0;
}
B. Asia区域制
二进制转换十进制,注意数据的范围很大。所以先把二进制转化为long long 类型的10进制数再转化为16进制字符串是错误的。
#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))
typedef long long ll;
const int maxn = 1e6 + 10;
void solve(string c){
if(c == "0000") printf("0");
else if(c == "0001")printf("1");
else if(c == "0010")printf("2");
else if(c == "0011")printf("3");
else if(c == "0100")printf("4");
else if(c == "0101")printf("5");
else if(c == "0110")printf("6");
else if(c == "0111")printf("7");
else if(c == "1000")printf("8");
else if(c == "1001")printf("9");
else if(c == "1010")printf("a");
else if(c == "1011")printf("b");
else if(c == "1100")printf("c");
else if(c == "1101")printf("d");
else if(c == "1110")printf("e");
else if(c == "1111")printf("f");
}
int main(){
int t;
scanf("%d", &t);
getchar();
while(t--){
string s;
cin >> s;
int len = s.length();
if(len % 4 == 1) s = "000" + s;
else if(len % 4 == 2) s = "00" + s;
else if(len % 4 == 3) s = "0" + s;
len = s.length();
for(int i = 0; i < len; i+=4){
string x;
for(int j = 0; j < 4; j++){
x += s[i+j];
}
solve(x);
}
printf("\n");
}
return 0;
}
C. Asia区域宫
表面上看是个BFS求最短路径,仔细看一下数据发现巨jb大,所以bfs 是不可行的。
观察题目:障碍物在迷宫中不能同行且不能同列。
所以。如果不能到达终点,图中只能是从左下到右上的墙。所以,标记每条斜线上的墙壁个数就好了。
#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))
typedef long long ll;
const int maxn = 1e6 + 10;
const int N = 10001;
int n, m, x, y, t, a[N];
int main(){
scanf("%d", &t);
while(t--){
bool flag = true;
scanf("%d%d", &n, &m);
for(int i = 0; i < m; i++){
scanf("%d%d", &x, &y);
int tes = x + y - 1;
a[tes] ++;
if(a[tes] >= tes) {
flag = false;
}
}
if(flag) printf("Yes %d\n", (n-1)*2);
else printf("No\n");
clr(a);
}
return 0;
}
D. Asia区域阵
待补
#pragma GCC optimize ("O3")
#pragma GCC optimize ("O2")
#include <bits/stdc++.h>
#include <ext/rope>
using namespace std;
using namespace __gnu_cxx;
#define met(s) memset(s, 0, sizeof(s))
#define rep(i, a, b) for(int i = a; i <= b; ++i)
template <class T> inline void scan_d(T &ret) {
char c; ret = 0;
while ((c = getchar()) < '0' || c > '9');
while (c >= '0' && c <= '9') {
ret = ret * 10 + (c - '0'), c = getchar();}}
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int MAXN = 1e2 + 10;
char str[MAXN][MAXN];
int dp1[MAXN][MAXN], dp2[MAXN][MAXN], vis[30];
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int T;
scanf("%d", &T);
while(T--) {
int n, m;
scanf("%d %d", &n, &m);
for(int i = 0; i < n; ++i) scanf("%s", str[i]);
for(int i = 0; i < n; ++i) {
for(int j = 0; j < m; ++j) {
dp1[i][j] = dp2[i][j] = 0;
memset(vis, 0, sizeof(vis));
for(int p = 0; ;++p) {
if(vis[str[i][j + p] - 'A'] || j + p >= m) break;
vis[str[i][j + p] - 'A'] = 1;
dp1[i][j]++;
}
memset(vis, 0, sizeof(vis));
for(int p = 0; ;++p) {
if(vis[str[i + p][j] - 'A'] || i + p >= n) break;
vis[str[i + p][j] - 'A'] = 1;
dp2[i][j]++;
}
// printf("# %d -> %d %d\n", i, j, dp2[i][j]);
}
}
int ans = 0;
for(int i = 0; i < n; ++i) {
for(int j = 0; j < m; ++j) {
for(int k = 0; k < dp2[i][j]; ++k) {
int cnt = INF;
for(int p = 0; p <= k; ++p) {
cnt = min(cnt, dp1[i + p][j]);
}
int res = k + 1;
for(int p = 0; p < cnt; ++p) {
res = min(res, dp2[i][j + p]);
}
// printf("# %d %d\n", cnt, res);
ans = max(ans, cnt * res);
}
}
}
printf("%d\n", ans);
}
return 0;
}
E. Mo的游戏
用一个数组标记一下上一次出现字符的位置,然后在遍历一遍选出最大的
#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))
#define line cout<<"--------------"<<endl
typedef long long ll;
const int maxn = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
char s[maxn];
int a[26], A[26];
int an[26], An[26];
int main(){
scanf("%s", s);
int len = strlen(s);
for(int i = 0; i < 26; i++){
a[i] = -1; A[i] = -1;
an[i] = len; An[i] = len;
}
for(int i = 0; i < len; i++){
if(s[i] >= 'a' && s[i] <='z'){
if(a[s[i]-'a'] == -1) a[s[i]-'a'] = i;
else{
int pos = i - a[s[i]-'a'];
an[s[i]-'a'] = min(an[s[i]-'a'], pos);
a[s[i]-'a'] = i;
}
}
else{
if(A[s[i]-'A'] == -1) A[s[i]-'A'] = i;
else{
int pos = i - A[s[i]-'A'];
An[s[i] - 'A'] = min(An[s[i] - 'A'], pos);
A[s[i]-'A'] = i;
}
}
}
for(int i = 0; i < 26; i++){
if(a[i] == -1 || an[i] == INF) continue;
else printf("%c:%d\n", 'a'+i, len-an[i]);
}
for(int i = 0; i < 26; i++){
if(A[i] == -1) continue;
else printf("%c:%d\n", 'A'+i, len-An[i]);
}
return 0;
}
F. Mo的极限
这个题出得很李战士。
要注意-0x^k 以及 同类项的合并。
#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))
#define line cout<<"--------------"<<endl
typedef long long ll;
const int maxn = 1e7 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
char u[maxn], d[maxn];
int upcnt, lowcnt;
struct node{
int k, n;
}up[maxn], low[maxn];
int gcd(int a, int b){
return b == 0 ? a : gcd(b, a % b);
}
bool cmp(node a, node b){
return a.n > b.n;
}
int main(){
scanf("%s%s", u, d);
int lu = strlen(u);
int ld = strlen(d);
for(int i = 0; i < lu; i++){
if(u[i] == 'x'){
int pos = i-1, temp = 0, op = 1;
while(u[pos] >= '0' && u[pos] <= '9') pos--;
if(u[pos] == '-') op = -1;
pos ++;
for(; pos < i; pos++)
temp = temp * 10 + (u[pos] - '0');
if(temp == 0) continue;
if(op == -1) temp *= op;
up[upcnt].k = temp;
pos = i+2; temp = 0; op = 1;
while(u[pos] >= '0' && u[pos] <= '9')pos++;
for(int j = i+2; j < pos; j++)
temp = temp * 10 + (u[j] - '0');
up[upcnt++].n = temp;
}
}
for(int i = 0; i < ld; i++){
if(d[i] == 'x'){
int pos = i-1, temp = 0, op = 1;
while(d[pos] >= '0' && d[pos] <= '9')pos--;
if(d[pos] == '-') op = -1;
pos ++;
for(; pos < i; pos++)
temp = temp * 10 + (d[pos] - '0');
if(temp == 0) continue;
if(op == -1) temp *= op;
low[lowcnt].k = temp;
pos = i+2; temp = 0; op = 1;
while(d[pos] >= '0' && d[pos] <= '9')pos++;
for(int j = i+2; j < pos; j++)
temp = temp * 10 + (d[j] - '0');
low[lowcnt++].n = temp;
}
}
sort(up, up+upcnt, cmp);
sort(low, low+lowcnt, cmp);
for(int i = 1; i < upcnt; i++)
if(up[i].n == up[0].n) up[0].k += up[i].k;
for(int i = 1; i < lowcnt; i++)
if(low[i].n == low[0].n) low[0].k += low[i].k;
if(lowcnt == 0 || upcnt == 0) {
printf("0\n"); return 0;
}
if(up[0].n == low[0].n){
int tex = gcd(up[0].k, low[0].k);
int xx = up[0].k/tex, yy = low[0].k/tex;
if(yy == 1 || yy == -1) printf("%d\n", xx);
else{
if((xx>0 && yy >0) || (xx < 0 && yy < 0))printf("%d/%d\n", xx, yy);
else printf("%d/%d\n", abs(xx)*-1, abs(yy));
}
}
else if(up[0].n > low[0].n){
if(up[0].k == 0) printf("0\n");
else printf("oo\n");
}
else printf("0\n");
return 0;
}
/*
-1000x^20+1000x^2
10000x^20-1000x^20
-1x^10+1x^10+0x^1
1x^0
*/
G. Mo的数学
正解为容斥定理,我用的质因数分解+打标记水过
#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))
#define line cout<<"--------------"<<endl
typedef long long ll;
const ll maxn = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
bool vis[maxn];
ll a[maxn];
ll n, m, num;
void get_factor(int x){
for(int i = 2; i*i <= x; i++){
if(x % i == 0){
a[num++] = i;
while(x % i == 0){
x /= i;
}
}
}
if(x != 1) a[num++] = x;
}
int main(){
while(scanf("%d%d", &n, &m) != EOF){
clr(a); num = 0;
memset(vis, 1, sizeof(vis));
get_factor(m);
//line;
ll ans = 1;
for(int i = 0; i < num; i++){
ll t = a[i];
for(int j = 1; t*j <= n; j++){
vis[t*j] = false;
}
}
for(int i = 2; i <= n; i++){
if(vis[i]) ans = ((ans % MOD )* (i % MOD )) % MOD;
}
printf("%lld\n", ans);
}
return 0;
}
标程:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD = 1e9 + 7;
const int N = 1e6;
int fac[N + 1] ;
void init(int n){
fac[0] = 1;
for (int i = 1; i <= n; i++){
fac[i] = fac[i - 1] * 1ll * i % MOD;
}
}
int inv (int a, int b, int c){
int s = 1, base = a % c;
while(b){
if(b & 1) s = s * 1ll * base % c;
base = base * 1ll * base % c;
b >>= 1;
}
return s;
}
int prm[30], sz = 0;
void get_prim(int n){
sz = 0;
for (ll i = 2; i * i <= n; i++){
if(n % i == 0){
prm[sz++] = i;
while(n % i == 0) n /= i;
}
}
if(n != 1) prm[sz++] = n;
// for(int i = 0; i < sz; i++) cout << prm[i] <<"\n";
}
int main(){
int n, m;
init(N);
while(cin >> n >> m){
get_prim(m);
int ans = 1;
for (int i = 0; i < (1 << sz); i++){
int p = 1, cnt = 0;
for (int j = 0; j < sz; j++){
if(i >> j & 1){
p *= prm[j];
cnt ++;
}
}
int s = n / p;
int val = fac[s] * 1ll * inv(p, s, MOD) % MOD;
ans = ans * 1ll * ((cnt & 1) ? inv(val, MOD - 2, MOD) : val) % MOD;
//cout << ans <<"\n";
}
cout << ans <<"\n";
}
return 0;
}
H. Mo的面积
简单计算几何
#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))
#define line cout<<"--------------"<<endl
typedef long long ll;
const int maxn = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int main(){
int x1,x2,y1,y2;
int q1,q2,w1,w2;
while(cin>>x1>>y1>>x2>>y2>>q1>>w1>>q2>>w2){
int xx=max(min(x1,x2),min(q1,q2));
int yy=max(min(y1,y2),min(w1,w2));
int xxup=min(max(x1,x2),max(q1,q2));
int yyup=min(max(y1,y2),max(w1,w2));
int ans = 0;
if(xxup>xx)
ans = fabs((xx)-(xxup))*fabs((yy)-(yyup));
int a = fabs(x1-x2) * fabs(y1-y2);
int b = fabs(q1-q2) * fabs(w1-w2);
ans = a + b - ans;
cout << ans << endl;
}
}
I. 安全距离
高级计算几何,待补
J. 简单递归
签到题
#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))
#define line cout<<"--------------"<<endl
typedef long long ll;
const int maxn = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = (int)1e9 + 7;
int main(){
int t;
cin >> t;
int a[maxn];
a[0] = a[1] = a[2] = 1;
for(int i = 3; i <maxn; i++){
a[i] = ((a[i-1] << 1) % MOD + (a[i-2] >> 1)) % MOD;
}
while(t--){
int n;
scanf("%d", &n);
printf("%d\n",a[n]);
}
return 0;
}
K. 高度期望
签到题
#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))
#define line cout<<"--------------"<<endl
typedef long long ll;
const int maxn = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int n, num = 0, k, a[maxn];
int main(){
ll sum = 0;
cin >> n >> k;
for(int i = 0; i < n; i++){
scanf("%d", &a[i]);
sum += a[i];
}
sort(a, a+n);
while(sum < k * n){
sum += (1000-a[num]);
num++;
}
cout << num << endl;
return 0;
}
L. 最优规划
最小生成树模板,
#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))
#define line cout<<"--------------"<<endl
typedef long long ll;
const ll maxn = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const ll N = 100010;
ll n, m, s;
ll x, y, d;
ll pre[N];
struct node{
ll x, y, d;
}p[N];
ll find(ll x){
if(x == pre[x]) return x;
else return pre[x] = find(pre[x]);
}
void mix(ll x, ll y){
ll dx = find(x);
ll dy = find(y);
if(dx != dy) pre[dx] = dy;
}
bool cmp(node a, node b){
return a.d < b.d;
}
int main(){
scanf("%lld%lld%lld", &n, &m, &s);
for(ll i = 0; i <= n; i++){
pre[i] = i;
}
for(ll i = 0; i < m; i++){
scanf("%lld%lld%lld", &x, &y, &d);
mix(x, y);
}
for(ll i = 0; i < s; i++){
scanf("%lld%lld%lld", &p[i].x, &p[i].y, &p[i].d);
}
sort(p, p+s, cmp);
ll sum = 0;
bool flag = false;
for(ll i = 0; i < s; i++){
ll dx = find(p[i].x);
ll dy = find(p[i].y);
if(dx != dy){
sum += p[i].d;
pre[dx] = dy;
}
}
ll cnt = 0;
for(ll i = 1; i <= n; i++){
if(i == find(i)) cnt++;
}
if(cnt == 1) printf("%lld\n", sum);
else printf("Concubines can't do it.\n");
return 0;
}