BestCoder Round #89

这次BC大家好像都比较反感,哎,其实没必要计较太多的,小渣个人觉得还好,过了两题,所以写下博客,总结一下,以免到时候忘了

1001.Fxx and string

题目意思非常简单,就是给个字符串找出三个下标满足等比数列的字符,第一个字符为 y ,第二个为 r ,第三个为 x ,这里要注意的就是等比数列可递增也可递减所以要检查两种情况。

BC官方题解

枚举 i 和等比数列公比q,但考虑到 q 有可能是t的形式,所以倒过来枚举一遍就可以了。

代码

#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 变为1的最小步骤,有两种操作:

  1. X=Xi(1<=i<=t)
  2. X k的倍数, X=Xk

这里直接列出状态转移方程:
dp[i] 表示从 1 变到i的最小步骤,列出方程如下

dp[i]=min{dp[ix]}+1{ix>=1}

通过观察我们发现,得到 dp[i] 最小可以直接从 [it,i] 中的最小值转移过来就可以了,所以直接用单调队列保存当前在 [it,i] 的最小值即可,这个地方好像用线段树处理会超时,应该是卡常数,渣渣不是很懂

官方题解

Fi 表示将 i 变为1的最少步骤,如果 k|i,Fi=min{Fj,Fik} ,否则 Fi=minFj ,其中 itji1
用单调队列维护一下就好了
时间复杂度 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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值