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\n",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;
}

猜你喜欢

转载自www.cnblogs.com/EchoZQN/p/12558099.html