E. Count The Blocks

Posted echozqn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了E. Count The Blocks相关的知识,希望对你有一定的参考价值。

E. Count The Blocks

这是一个计数题,又把我卡自闭了。。。之前也碰到过类似的题目,这次居然还没有写出来,感觉自己还是太菜了,加油补题吧。

题目大意:

给你一个数字 (n),代表的是数的长度,该数可以有前导零,定义连续相同的数可以组成一个块,如果有 (x) 个连续相同的数,则认为这个块大小是 (x)

问:有n个数字的这个数,可以组成大小为 (i) 的块的数量是多少。

答案输出一行 (n) 个数,第 (i) 个数表示大小为 (i) 的块的数量。

题解:

这种题目就很容易把自己绕进去,所以我们不要每一个去仔细推,而是思考:我要构造大小为 (i) 的块,应该如何去构造。

是不是选一块大小为 (i) 的块,然后这个块如果在中间,则两边的数字应该不同,其他的块则无所谓,如果在边界,则只要满足一边的数字和这个块不同即可,然后统计答案。

这个会不会出现重复呢?或者会不会少统计了呢?

这两个看起来有矛盾的提问,其实就解决了这两个问题。

因为我每一个位置只统计了一次,但是可能我假设的这个位置出现大小为 (i) 的块不止一个,所以才会有疑问会不会少统计了。

同时因为每一个位置都统计了一次,所以可能会有两个位置,出现大小为 (i) 的块的数量及位置都相同,所以才会有疑问会不会重复统计了。

确实有可能会出现 (x) 个位置,此时出现大小为 (i) 的块的数量及位置都相同,但是每一次我只统计了一次,并没有乘以 (x) 这个数,所以不会重复,也不会丢掉一些数。

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn=2e5+10;
const int mod=998244353;
typedef long long ll;
ll dp[maxn];
ll binpow(ll x,ll n){
    ll ans=1;
    while(n){
        if(n&1) ans=(ans*x)%mod;
        x=(x*x)%mod;
        n>>=1;
    }
    return ans;
}
int main(){
    int n;
    scanf("%d",&n);
    dp[n]=10,dp[n-1]=180;
    for(int i=n-2;i>=1;i--){
        dp[i]=10*9*binpow(10,n-i-1)%mod*2%mod;
//        printf("dp[%d]=%lld
",i,dp[i]);
    }
    for(int i=n-2;i>=1;i--){
        dp[i]=(dp[i]+10*9*9*binpow(10,n-i-2)%mod*(n-i-1)%mod)%mod;
    }
    for(int i=1;i<=n;i++) printf("%lld ",dp[i]);
    return 0;
}

以上是关于E. Count The Blocks的主要内容,如果未能解决你的问题,请参考以下文章

E. Count The Blocks(找数学规律)

Count The Blocks

Count The Blocks CodeForces - 1327E oeis

Codeforces 1327E - Count The Blocks (dp)

矩阵乘法&&dp加速矩阵的思路(E. Wet Shark and Blocks)

Codeforces Round #341 (Div. 2) E. Wet Shark and Blocks(矩阵优化DP)