B. Sum of Two Numbers
时间:2024-07-06
原题:Codeforces Round 851 (Div. 2)B. Sum of Two Numbers
标签:[[数论]]
题意
一个数字
思路
对于每一位,都可以将其平均,每次遇到奇数就分配给
代码
void solve() {
cin >> n;
if (n % 2 == 0) {
cout << n / 2 << " " << n / 2 << endl;
return;
}
// a1,a2是最终答案
int a1=0, a2=0;
// i表示分解的位数
int i = 0;
// c表示分解n的第i位时如果出现奇数将较大的一个数给a1还是a2
int c = 0;
while (n) {
int d = pow(10, i);
int base = n % 10;
int base1 = base / 2, base2 = base / 2 + base % 2;
if (c % 2 == 1) {
a1 += base1 * d;
a2 += base2 * d;
if(base1!=base2)c++;
}
else {
a1 += base2 * d;
a2 += base1 * d;
if (base1 != base2)c++;
}
n /= 10;
i++;
}
cout << a1 << " " << a2 << endl;
}C. New Year and Rating
时间:2024-07-06
原题:Good Bye 2016 C. New Year and Rating
题意
1900是一个分界线,线上规定为等级1(包括1900),线下规定为等级2
有
思路
对于等级和得分,我们可以用一个
即如果为等级1,并且是加分,
并且可以知道此时的分数变化对上下限不产生影响
如果等级为1,但是是扣分,
- 如果等级没掉,可以确定下限
- 如果等级掉了,可以确定上限
最后如果出现错误的等级变化或者上限小于下限,则Impossible
代码
#define IMP "Impossible"
#define INF "Infinity"
#define int long long
#define rep(i,j,k) for(i=(j);i<(k);i++)
const int N = 2e5+10;
int ii, jj, kk;
int n;
struct Node {
int c, d;
}node[N];
int sum[N];
void solve() {
cin >> n;
sum[0] = 0;
rep(ii, 1, n+1) {
cin >> node[ii].c >> node[ii].d;
sum[ii] = sum[ii - 1] + node[ii].c;
}
//上界下界,包含边界
int to = 1e9, bo = -1e9;
if (node[1].d == 1) bo = 1900;
else to = 1899;
rep(ii, 1, n) {
//在线上往下降
//在线下往上升
//线上1 上升1
int value = (node[ii].d == 1 ? 1 : -1) * (node[ii].c >= 0 ? 1 : -1);
if (node[ii].c == 0 && node[ii].d!=node[ii+1].d) {
cout << IMP << endl;
return;
}
//有判断价值
if (value < 0) {
//当前在1,但是掉分
if (node[ii].d == 1) {
//掉分没掉下1
if (node[ii + 1].d == 1) {
bo = max(bo, 1900 - sum[ii]);
}
//掉分掉到2
else {
to = min(to, 1899 - sum[ii]);
}
}
else {
//上大分
if (node[ii + 1].d == 1) {
bo = max(bo, 1900 - sum[ii]);
}
//上小分
else {
to = min(to, 1899 - sum[ii]);
}
}
}// 可以融合成一个
// value>0时
// 如果线上上分变成线下||线下掉分变成线上
else {
if (node[ii].d != node[ii + 1].d) {
cout << IMP << endl;
return;
}
}
}
if (bo > to) {
cout << IMP << endl;
}
else if (to != 1e9) {
cout << to + sum[n] << endl;
}
else {
cout << INF << endl;
}
}D. Petya, Petya, Petr, and Palindromes
时间:2024-07-06
原题:Codeforces Round 861 (Div. 2)D. Petya, Petya, Petr, and Palindromes
思路来源:https://zhuanlan.zhihu.com/p/618268493
题意
给定序列
比如
思路
首先排除暴力,但是如果要计算所有不同的对数,必须要每个比较一次,则这个思路不行
所以选择计算所有的可能,然后再减去相同的对数。
1
在一开始对题目的尝试中可以获知当前位要与其他邻近的同奇偶性的位置进行比较
那么我们可以先按奇偶存储一个数的下标,当下次再遇到这个数的下标时根据k判断是否成立
比如对于
遍历到
遍历到
遍历到
遍历到
2
对于基本的流程了解后,现在需要确定初始所有的答案,和成对的条件
我们引入对称中心的概念,记为c,可知
那么对于初始答案,有
相乘则为答案
对于成对的条件,记当前遍历到的位数为i,与之对应的成对下标为j,可知
将c带入进上面的式子,就是
还有一个条件,
综上,
最后用lower_bound和upper_bound快速获取答案
代码
const int N = 2e5 + 10;
int n, k;
vector<int> v[N][2];
void solve() {
cin >> n >> k;
// 给ans赋初值
int ans = (n - k + 1) * (k / 2);
int x = 0;
rep(ii, 1, n + 1) {
// 对于每个x 看有没有能与之配对且符合条件的
cin >> x;
auto posl = lower_bound(alli(v[x][ii & 1]), max(k - ii + 1, ii - k + 1));
auto posr = upper_bound(alli(v[x][ii & 1]), 2 * n - k - ii + 1);
//cout << "ii:" << ii << " posl:" << posl << " posr:" << posr << endl;
ans -= posr - posl;
v[x][ii & 1].push_back(ii);
}
cout << ans << endl;
}