Codeforces Round #370 (Div. 2)
链接
712A Memory and Crow
题意:给出序列a,a[i] = b[i] - b[i + 1] + b[i + 2] - b[i + 3]…,求序列b。
题解:容易看出b[i] = a[i] + a[i+1],扫描一遍输出。
712B Memory and Trident
题意:给出一个包含’L’、’R’、’U’、’D’的指令序列,可以改变序列中的某个指令,问你如果想执行完指令后回到原点,最少需要改多少个指令(如果回不到就输出-1)。
题解:如果是奇数个指令则无解,偶数个一定有解,想一下一个能回到原点的指令序列一定是’L’个数等于’R’个数,’U’个数等于’D’个数,所以我们对左右指令个数作差,上下指令个数作差,再求和就接近结果了。如果左右指令个数差为奇数,那么上下指令个数差也为奇数,那改变这个单独的指令就可以了。所以答案是 abs(l - r) / 2 + abs(u - d) / 2 + abs(l - r) % 2。
712C Memory and De-Evolution
题意:有一个边长为x的正三角形,现在想把它变成边长为y的正三角形(y < x),并且每次只能减小一条边,并且减小后,这三边仍能构成三角形,问最少减小几次可满足条件。
题解:反过来想,从边长为y的正三角形逐边增加到边长为x的正三角形需要几步,贪心的思想,每次尽可能增大,记录次数就是结果了。
712D Memory and Scores
题意:A、B两人在玩一个游戏,他们起始的分值是a和b,游戏共t局,每局他们随机取一个[-k, k]的整数加到自己当前的分值上,A想知道有多少种情况他能赢(只要有一局他们取得的值不同就算不同情况)。
题解:dp+差分数组。d[i][j]表示第i局后,A比B高j分有多少种情况(注意这里j可为负值)。初始状态是d[0][0] = 1,d[i][j]可以给区间[ d[i+1][j-k], d[i+1][j+k] ]提供d[i][j]的贡献,区间提高相同值可以用差分数组+前缀和在O(1)内完成,由于我们只需要t局结束后的,可以用滚动数组优化一下空间。答案就是d[b - a + 1][t]右侧的累和。
这里可以优化一下常数,就是记录一下每局结束后的边缘分值l和r,应该会快将近一倍(不优化应该也可以过)。
po个代码:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long lint;
const lint mod = 1000000007;
#define zero (200200)
lint ta[zero << 1], tb[zero << 1];
int k, t;
pair<int, int> dp(int cur, int l, int r)
{
//cout << "dp()" << endl;
memset(tb, 0, sizeof(tb));
for(int i = l; i <= r; i++)
{
tb[i - k] = (tb[i - k] + ta[i]) % mod;
tb[i + k + 1] = ((tb[i + k + 1] - ta[i]) % mod + mod) % mod;
}
for(int i = l - k; i <= r + k; i++)
{ tb[i] += tb[i-1]; tb[i] %= mod; }
l -= k, r += k;
/*
for(int i = l; i <= r; i++)
{
printf("[%lld] ", tb[i]);
} printf("\n");
*/
memset(ta, 0, sizeof(ta));
for(int i = l; i <= r; i++)
{
ta[i - k] = (ta[i - k] + tb[i]) % mod;
ta[i + k + 1] = ((ta[i + k + 1] - tb[i]) % mod + mod) % mod;
}
for(int i = l - k; i <= r + k; i++)
{ ta[i] += ta[i-1]; ta[i] %= mod; }
l -= k, r += k;
for(int i = l; i <= r; i++)
tb[i] = 0;
/*
for(int i = l; i <= r; i++)
{
printf("[%lld] ", ta[i]);
} printf("\n");
*/
if(cur == t) return make_pair(l, r);
else return dp(cur + 1, l, r);
}
int main()
{
int a, b;
cin >> a >> b >> k >> t;
ta[zero] = 1;
pair<int, int> A = dp(1, zero, zero);
/*
for(int i = A.first; i <= A.second; i++)
{
printf("[%lld] ", ta[i]);
} printf("\n");
*/
lint o = 0;
for(int i = zero - a + b + 1; i <= A.second; i++)
{ o += ta[i]; o %= mod; }
cout << o << endl;
return 0;
}
712E Memory and Casinos
这题不会,说是数学题,短期内应该也不打算补了吧。。。I hate math。。。