CodeFoeces 1327E - Count The Blocks【打表/组合数学】

题意:

统计 \(0,1,2,⋯,10^{n−1}\) 所有数字中不同长度的连续区间数。
例如 \(0111223\) 中有 \(2\) 段长度为 \(1\) 的区间, \(1\) 段长度为 \(2\) 的区间, \(1\) 段长度为 \(3\) 的区间。(如果数字不足 \(n\) 位需要补充前导零)
数据范围:\(1 \leq n \leq 2*10^5\)

解法 \(1\)

打表,找规律:
\(num[n]=10;\)
\(num[n-1]=180;\)
\(num[n-2]=2610;\)
\(num[i]=20*num[i+1]-100*num[i+2];(0<i<n-2)\)

代码:

#include <bits/stdc++.h>
using namespace std;
const int mod=998244353;
typedef long long ll;
const int N=2e5+5;
ll num[N];
int main()
{
    int n;
    scanf("%d",&n);
    num[n]=10;
    if(n>1)
        num[n-1]=180;
    if(n>2)
        num[n-2]=2610;
    for(int i=n-3;i>=1;i--)
        num[i]=((20*num[i+1]%mod)-(100*num[i+2]%mod)+mod)%mod;
    for(int i=1;i<=n;i++)
        printf("%lld%c",num[i],i==n?'\n':' ');
    return 0;
}

解法 \(2\)

1.当 \(i=n\) 时,\(num[i]=10\)
2.当 \(i<n\) 时,考虑所求长度为 \(i\) 的序列在两端的情况。
\(ans=2*10*9*10^{n-i-1}\)
3.当 \(i<n-1\) 时,考虑所求长度为 \(i\) 的序列在中间的情况。
\(ans=(n-1-i)*10*9^2*10^{n-i-2}\)
用快速幂就可以求解。
代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353;
ll power(ll a,int b)
{
    ll res=1;
    while(b)
    {
        if(b&1)
            res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res%mod;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        ll res=0;
        if(i==n)
            res=10;
        if(i<n)
            res+=(2LL*10*9*power(10*1LL,n-i-1)%mod);
        if(i<n-1)
            res+=(1LL*(n-i-1)*10*9*9*power(10*1LL,n-i-2)%mod);
        printf("%lld%c",(res+mod)%mod,i==n?'\n':' ');
    }
    return 0;
}

参考博客

猜你喜欢

转载自www.cnblogs.com/1024-xzx/p/12567509.html