这次BC大家好像都比较反感,哎,其实没必要计较太多的,小渣个人觉得还好,过了两题,所以写下博客,总结一下,以免到时候忘了
1001.Fxx and string
题目意思非常简单,就是给个字符串找出三个下标满足等比数列的字符,第一个字符为 ′y′ ,第二个为 ′r′ ,第三个为 ′x′ ,这里要注意的就是等比数列可递增也可递减所以要检查两种情况。
BC官方题解
枚举
i
和等比数列公比
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 1e4 + 5;
char S[MAXN];
int main(){
int _;
scanf("%d", &_);
while(_ --){
scanf("%s", S + 1);
int len = strlen(S + 1);
LL ans = 0;
for(int i = 1;i <= len;i ++){
for(int j = 1; i * i * j <= len;j ++){
if(S[j] == 'y' && S[i * j] == 'r' && S[i * j * i] == 'x') ans ++;
if(S[j] == 'x' && S[i * j] == 'r' && S[i * j * i] == 'y') ans ++;
}
}
printf("%I64d\n", ans);
}
return 0;
}
1002.Fxx and game
这道题目求解的是
X
变为
- X=X−i(1<=i<=t)
- 若
X
为
k 的倍数, X=Xk
这里直接列出状态转移方程:
dp[i]
表示从
1
变到
dp[i]=min{dp[i−x]}+1{i−x>=1}
通过观察我们发现,得到 dp[i] 最小可以直接从 [i−t,i] 中的最小值转移过来就可以了,所以直接用单调队列保存当前在 [i−t,i] 的最小值即可,这个地方好像用线段树处理会超时,应该是卡常数,渣渣不是很懂
官方题解
设
Fi
表示将
i
变为
用单调队列维护一下就好了
时间复杂度
O(n)
代码
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef pair<int,int>PII;
typedef long long LL;
const int MAXN = 1e6 + 5;
const int INF = 0x3f3f3f3f;
int X, k, t;
int dp[MAXN << 1];
PII Q[MAXN];
int head, tail;
int main() {
int _;
scanf("%d", &_);
while(_ --) {
scanf("%d%d%d", &X, &k, &t);
memset(dp, 0x3f, sizeof(dp));
dp[1] = 0;
head = 0, tail = 0;
Q[tail ++] = PII(dp[1], 1);
for(int i = 2; i <= X; i ++) {
while(head < tail && i - Q[head].second > t) head ++;
if(head < tail){
dp[i] = Q[head].first + 1;
}
if(i % k == 0){
dp[i] = min(dp[i], dp[i / k] + 1);
}
while(head < tail && Q[tail - 1].first > dp[i]) tail --;
Q[tail ++] = PII(dp[i], i);
}
printf("%d\n", dp[X]);
}
return 0;
}