zoukankan      html  css  js  c++  java
  • CF1327E Count The Blocks 简单计数

    题面:

    题意:
    给定(n),求(0~10^n-1)中总共的连续相同长度块分别有多少个,例00032,有1个长度为3的连续块,2个长度为1的连续块
    思路:
    一个长度为k的块我们可以看作长度为(1)的块,其价值为(k)
    (f[n]=9^{n-1}*10)表示连续(n)个长度为(1)的块的方案数
    (ans[i]=sum_{j=2}^{n-i+1} j*f[j]*C_{n-i-1}^{j-2})
    因为(1)个连续长度为(1)的块一定只能给价值(n),所以(j)(2)开始
    (ans[i])相当于求价值为i的块的方案数
    此时枚举连续(j)个长度为(1)的块,有(j)个位置可以放价值(i),所以乘上(j)
    然后求将剩下价值(n-i)放入(j-1)个位置中,每个位置最少为(1)的方案数,即(C_{n-i-1}^{j-2}),乘上之前求出来的方案数
    最后将所有枚举的j得到的方案数求和就是(ans[i])
    但是这个做法时间复杂度怎么也得(O(n^2))级别的,肯定过不了
    后来仔细思考发现,我想复杂了,实际上这题的计数并用不到组合数,而是简单计数,是线性的
    考虑求ans[i],其相当于选择一个位置放只连续i个的相同的数,其他位置的数是什么并不重要
    于是(ans[i]=2*10*9*10^{n-i-1}+(n-i-1)*10*9*9*10^{n-i-2})
    前面的式子表示将只连续(i)个相同的放在头尾,那么需要一个间隔位置不同,所以(*9),其他位置随便,所以(*10^{n-i-1})
    后面的式子表示将只连续(i)个相同的放在中间,那么需要两个间隔位置不同,所以(*9*9),其他位置随便,所以(*10^{n-i-2})
    最后注意一下范围细节
    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<stack>
    #include<queue>
    #include<vector>
    #include<cstring>
    #include<string>
    #include<map>
    #define ll long long
    #define mod 998244353 
    using namespace std;
    int n,ans;
    int pw[200001];
    int main()
    {
        scanf("%d",&n);
        pw[0]=1;for(int i=1;i<=n;i++)pw[i]=(ll)pw[i-1]*10%mod;
        for(int i=1;i<=n;i++)
        {
          ans=0;
          if(i==n)ans=10;
          else ans=(ll)2*10*9*pw[n-i-1]%mod;
          if(n-i-2>=0)ans=((ll)ans+(ll)(n-i-1)*10*9*9*pw[n-i-2]%mod)%mod;
          printf("%d ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    为什么ip层收到的报文可能已经设置了路由
    由socket fd泄漏想到的一些问题
    Html.DropDownLis绑定数据库
    CSS 属性备注
    获取IP
    读取TXT并筛选数据写入新建TXT
    C#打印图片
    C#生成二维码
    NPOI操作Excel
    Bootstrap
  • 原文地址:https://www.cnblogs.com/worcher/p/12557665.html
Copyright © 2011-2022 走看看