欢迎光临散文网 会员登陆 & 注册

AtCoder Beginner Contest 249 E - RLE

2022-05-11 03:44 作者:Asunataisiki  | 我要投稿

题意:求满足原长度为n,且经过转换规则之后长度严格小于n的原字符串有多少种

其中,转换规则为,将连续的字母表示为原字母+字母个数,例如aaa转化为a3

思路:一眼dp,首先考虑暴力求解,dp%5Bi%5D%5Bj%5D表示原串长度为 i 且转换长度后为 j 的数量,那么考虑在当前长度i的情况下,在后面接一个长度为k的字符串(每个字母均相同),可以表示为dp%5Bi%5D%5Bj%5D%2B%3Ddp%5Bi-k%5D%5Bj-len(k)%5D*25,其中len(k)表示经过转换规则之后的长度,乘25的原因是,需要与原串最后一个字母不同,共有25中情况,可以发现这是个n%5E3的复杂度,需要优化

这里面首先能想到的就是优化 k

k%5Cin%20%5B1%2C10)%2Clen(k)%3D2

k%5Cin%20%5B10%2C100)%2Clen(k)%3D3

k%5Cin%20%5B100%2C1000)%2Clen(k)%3D4

k%5Cin%20%5B1000%2C10000)%2Clen(k)%3D5

发现k可以分区间了,所以f%5Bi%5D%5Bj%5D%20%3D%20(%5Csum_%7Bk%20%3D%201%7D%5E%7B9%7Df%5Bi%20%20-%20k%5D%5Bj-2%5D%2B%5Csum_%7Bk%20%3D%2010%7D%5E%7B99%7Df%5Bi-k%5D%5Bj-3%5D%2B...%2B%5Csum_%7Bk%20%3D%201000%7D%5E%7B9999%7Df%5Bi-k%5D%5Bj-5%5D%20)

用前缀和来优化掉每一个求和

注意处理边界,但是不懂为什么要在前缀和相减的时候加上p,不加就wa,加了就过了

#include<bits/stdc++.h>
#define endl '\n'
#define fr first
#define se second
#define mem(x, y) memset(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int inf = 0x3f3f3f3f;
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
//右左上下
const int N = 3005;
LL f[N][N], sum[N][N];
///f表示长度为i的字符串,用计数法表示后长度为j的数量
///s表示长度为2 ~ i的字符串,用计数法表示后长度为j的数量

void solve()
{
    int n, p;
    cin >> n >> p;
    //f[0][0] = 1;
    for(int i = 1; i <= n; i++) {
        int k = 1 + to_string(i).size();
        if(k < n) {
            f[i][k] += 26; f[i][k] %= p;
        }
        ///题目要求压缩后的长度j < n,所以这里不取等
        for(int j = 2; j <= 2 * i && j < n; j++) {
            f[i][j] += 25 * (p + sum[max(0, i - 1)][max(0, j - 2)] - sum[max(0, i - 10)][max(0, j - 2)]) % p;
            f[i][j] += 25 * (p + sum[max(0, i - 10)][max(0, j - 3)] - sum[max(0, i - 100)][max(0, j - 3)]) % p;
            f[i][j] += 25 * (p + sum[max(0, i - 100)][max(0, j - 4)] - sum[max(0, i - 1000)][max(0, j - 4)]) % p;
            f[i][j] += 25 * (p + sum[max(0, i - 1000)][max(0, j - 5)] - sum[max(0, i - 10000)][max(0, j - 5)]) % p;
            f[i][j] %= p;
            sum[i][j] = sum[i - 1][j] + f[i][j];
            sum[i][j] %= p;
        }
    }
    LL ans = 0;
    for(int i = 1; i < n; i++) {
        ans += f[n][i];
        ans %= p;
    }
    cout << ans << endl;
}

int main() 
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    int T = 1;
    //cin >> T;
    while(T--) solve();
    return 0;
}
// 315397365


AtCoder Beginner Contest 249 E - RLE的评论 (共 条)

分享到微博请遵守国家法律