国科信息学薪火计划模拟赛Round4题解
A. 游戏
首先,数字这么长,要用字符串输入
怎么确定重新排列后最大的30的倍数呢??首先末尾一定为0,因为它一定是3的倍数也是10的倍数,所以有一个特点:数位和加起来是3的倍数,如果不是,那么不管怎么排列都不行,所以如果有解,只需要确定末尾为0就行了然后判断大整数是否被30整除。
#include<iostream>
#include<vector>
#include<algorithm>
#include <iomanip>
#include <math.h>using namespace std;int main()
{string str = "";cin >> str;int sum = 0;sort(str.begin(), str.end());reverse(str.begin(), str.end());if (str[str.length() - 1] != '0'){cout << "-1" << endl;return 0;}for (int i = 0; i < str.length() ; i++){sum = (sum*10+(int) str[i] - '0')%30;}if (sum != 0){cout << "-1" << endl;return 0;}cout << str;return 0;
}
B. 字符
暴力写法就是直接拼接,判断一下
30分是小范围,另外的30分是X比较小,可以暴力拼接,当A串长度超过X就可以停了
暴力参考写法:
#include <bits/stdc++.h>
using namespace std;int main()
{freopen("string.in","r",stdin);freopen("string.out","w",stdout);int n,m,t,k;cin >> n >> m >> t;string a,b,c;cin >> a >> b;c += a;c += b;c += b;c += a;c += b;c += a;c += a;c += b;c += b;c += a;c += a;c += b;c += a;c += b;c += b;c += a;c += b;c += a;c += a;c += b;c += a;c += b;c += b;c += a;c += a;c += b;c += b;c += a;c += b;c += a;c += a;c += b;n = c.size();for(int i = 1;i <= t;i++){cin >> k;cout << c[(k-1) % n] << "\n";}fclose(stdin);fclose(stdout);return 0;
}
如何得到正解??
全暴力拼接肯定不行,我们考虑一步步拆解,可以用地推的方式来计算出A[?]的长度,得到长度的话就逐步往回递归寻找答案,不断锁定第X个符号处于哪一段,不断往回找。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e3+5,maxm=1e4+5;
const ll inf=1e18;
ll la[maxn],lb[maxn];
char sa[maxm],sb[maxm];
char getA(int n,ll x);
char getB(int n,ll x);
char getA(int n,ll x){if (!n) return sa[x];if (x<la[n-1]) return getA(n-1,x);return getB(n-1,x-la[n-1]);
}
char getB(int n,ll x){if (!n) return sb[x];if (x<lb[n-1]) return getB(n-1,x);return getA(n-1,x-lb[n-1]);
}
int main(){int n,m,t;scanf("%d%d%d",&n,&m,&t);scanf("%s%s",&sa,&sb);la[0]=n,lb[0]=m;for (int i=1;i<maxn;i++)la[i]=lb[i]=min(inf,la[i-1]+lb[i-1]);while (t--){ll x;scanf("%lld",&x);putchar(getA(935,x-1));puts("");}return 0;
}
C. 区间
暴力写法就是,计算全部区间覆盖最多的一个点,从这个点切割分开,能得到的新区间数量肯定是最多的,然后重复下去,就拿到暴力分了
如何拿满分呢??
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define int long long
using namespace std;const int MAXN = 1e5 + 5;
const int INF = 0x3f3f3f3f3f3f3f3f;
int inline read(){int x = 0, f = 0; char ch = getchar();while(ch < '0' || ch > '9') f ^= (ch == '-'), ch = getchar();while(ch >= '0' && ch <= '9') x = x * 10 + (ch ^ 48), ch = getchar();return f ? -x : x;
}int n, m, totp, ans;
pair<int,int> p[MAXN * 2];int cur, cnt[MAXN];signed main(){int T = read();for(int test_id = 1; test_id <= T; ++test_id){totp = 0; cur = 0; ans = 0;memset(cnt, 0, sizeof(cnt));n = read(); m = read();for(int i = 1; i <= n; ++i){int l = read(), r = read();if(l + 1 >= r) continue;p[++totp] = make_pair(l + 1, -1);p[++totp] = make_pair(r, 1);}sort(p + 1, p + totp + 1);for(int i = 1; i <= totp; ++i){cnt[cur] += p[i].first - p[i - 1].first ;cur -= p[i].second;}cnt[0] = INF;for(int i = n; i >= 0 && m; --i){int get = min(m, cnt[i]);ans += get * i; m -= get;}// for(int i = 0; i <= n; ++i)// fprintf(stderr, "%lld " , cnt[i]);// fprintf(stderr, "\n");printf("Case #%lld: %lld\n", test_id, ans + n);}return 0;
}
D. 阿木木的单挑
思维+贪心模拟
参考题解
E. 双序列问题
贪心+二分答案
参考题解