Contestant. Rank 2691. Rating +7.
A. One and Two
题意
给定一个包含
思路
维护一个后缀和,统计前面和后面的
时间复杂度:
对应AC代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1010;
int a[N], suf[N];
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t, n;
cin >> t;
while(t --){
cin >> n;
memset(a, 0, sizeof a);
memset(suf, 0, sizeof suf);
for(int i=1;i<=n;i++)cin >> a[i];
for(int i=n;i>=1;i--) {
suf[i] = suf[i + 1];
if(a[i] == 2) suf[i] ++;
}
int tot = 0;
bool f = true;
for(int i=1;i<n;i++){
if(a[i] == 2) tot ++;
if(tot == suf[i + 1]){
cout << i << '\n';
f = false;
break;
}
}
if(f) cout << -1 << '\n';
}
return 0;
}
你一个大铸币是怎么会想着纯模拟的啊((
B. Sum of Two Numbers
题意
给定一个整数
思路1
我们不妨除以
若
对上述思路的证明
我们令除
首先,我们只需考虑
考虑到个位为
那么,我们来考虑高位的情况:
若
的十位小于 ,不难发现,我们只需让 的十位变为 的十位加一,这样可以让 的所有位之和相等,也就是说,只要输出 即可; 若
的十位为 ,那么事态发生了微妙的变化:存在进 位的情况了。但,只要百位不是奇数,我们依然可以按照情况 找出一个答案; 若
的十位为 ,百位为奇数,且千位不为 时,那么按照上述操作后, 存在进 位的情况,方案不成立了; 此时,有趣的现象出现了:
和 恰好差了 ,那么我们不妨把个位改为 ,此时,我们可以构造出 ,满足差值为 ; 当千位、乃至更高位都为
时,差值会更大,但 根据打表我们不难发现,和 的差值均为 的倍数,那么我们只要让高位的差值降低,最后一定能得到解。
时间复杂度:懒得分析
对应AC代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1010;
int a[N], suf[N];
int cal(int x){
int res = 0;
while(x > 0){
res += x % 10;
x /= 10;
}
return res;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t, n;
cin >> t;
while(t --){
cin >> n;
int p = n / 2, q = n - p;
while(abs(cal(p) - cal(q)) > 1) p += 5, q -= 5;
cout << p << ' ' << q << '\n';
}
return 0;
}
思路2
按照上述证明的思路,我们可以找出一个规律:
首先,偶数直接输出
其次,个位不是
否则,从证明思路,我们可以发现,以
因此,对于该情况,我们只需从低位向高位枚举,找出第一个不是
时间复杂度:
对应AC代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1010;
int ans[10] = {0, 1, 2, 10, 18, 100, 180, 1000, 1800, 10000};
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t, n;
cin >> t;
while(t --){
cin >> n;
if(n % 2 == 0) cout << n / 2 << ' ' << n / 2 << '\n';
else if(n % 10 != 9) cout << n / 2 << ' ' << n - n /2 << '\n';
else{
int p = n / 2, q = n - p;
int cnt = 0;
while(n % 10 == 9) n /= 10, cnt ++;
int val = n % 10;
if(val == 0) val = 9, cnt --;
if(val % 2 == 0) cout << p + ans[cnt - 1] * 5 << ' ' << q - ans[cnt - 1] * 5 << '\n';
else cout << p + ans[cnt] * 5 << ' ' << q - ans[cnt] * 5 << '\n';
}
}
return 0;
}
我好蠢
C. Matching Numbers
题意
给定一个整数
思路
我们不难发现,若是偶数的话,我们是找不出这个序列的,可以通过计算验证。
对于奇数的话,我们可以根据等差公式算出中间的值
输出即可。
时间复杂度:
对应AC代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1010;
int a[N], suf[N];
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t, n;
cin >> t;
while(t --){
cin >> n;
if(n % 2 == 0) cout << "No\n";
else{
cout << "YES\n";
for(int i=1;i<=n/2+1;i++){
cout << i * 2 - 1 << ' ' << 2 * n - i + 1 << '\n';
}
for(int i=1;i<=n/2;i++){
cout << i * 2 << ' ' << 2 * n - i - n / 2 << '\n';
}
}
}
return 0;
}
md,思路很清晰但wa了一发
D. Moving Dots
题意
给定
思路
我们将问题转化为:对于所有
那么,对于这个区间的确定,我们不妨来考虑下面的两种情况:
- 对于汇聚到左边的点,最左边的点
应该向右边移动,那么我们找出从 开始,往前找第一个向左移动的即可,也就是说,应满足 。 - 同理,满足
。
综上,
考虑到单调性,我们可以用二分查找。
时间复杂度:
对应AC代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 3010;
int x[N], pows[N], mod = 1e9 + 7;
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
pows[0] = 1;
for(int i=1;i<=n;i++) { //Awesome but strange solution from the official tutorial.
cin >> x[i];
pows[i] = (pows[i - 1] * 2) % mod;
}
int ans = 0;
for(int i=1;i<n;i++)
for(int j=i+1;j<=n;j++) {
int l = lower_bound(x + 1, x + n + 1, 2 * x[i] - x[j]) - (x + 1),
r = lower_bound(x + j + 1, x + n + 1, 2 * x[j] - x[i]) - x;
ans = (ans + pows[n - r + l + 1]) % mod;
}
cout << ans << '\n';
return 0;
}
妙啊
- 本文链接 https://floating-ocean.github.io/blog_old/posts/989416061/
- 版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!