CodeForces - 1327E Count The Blocks(组合数学)

题目链接:点击查看

题目大意:给出一个 n ,表示出 0 ~ 10^n - 1 内的所有整数,且用前导零补齐,即所有的数长度都为 n ,规定连续的且数值相同的一段称为block,现在问对于每个 i ∈ [ 1 , n ] ,10^n 个数中共有多少个长度为 i 的 block

题目分析:比较简单的一道组合数学题目,分情况讨论一下就好了:

  1. i == n:显然答案只有十种情况
  2. i < n:考虑答案在两头的情况,即连续的block为橙色的部分:00000 或 00000,此时的答案为10*9*2*10^(n-i-1)
    1. 10是橙色部分的取值范围
    2. 9是与橙色部分相邻的首个黑色数字的取值范围
    3. 2是橙色部分在左侧或右侧两种情况
    4. 10^(n-i-1)是其余黑色部分的取值范围
  3. i < n - 1:考虑答案不在两头的情况,即连续的block为橙色部分:00000 00000 等等,此时答案为10*(n-i-1)*9*9*10^(n-i-2)
    1. 10是橙色部分的取值范围
    2. (n-i-1)是橙色部分通过平移,可以在不同位置有(n-i-1)种情况,如上面 i = 2,n = 5 时,就有 5 - 2 - 1 = 2 (种)情况
    3. 9是橙色部分左侧的第一个黑色数字的取值范围
    4. 9是橙色部分右侧的第一个黑色数字的取值范围
    5. 10^(n-i-2)是其余黑色部分的取值范围

然后配合快速幂实现就好了

代码:
 

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;
      
typedef long long LL;

typedef unsigned long long ull;
      
const int inf=0x3f3f3f3f;
 
const int N=2e5+100;

const int mod=998244353;

LL q_pow(LL a,LL b)
{
	LL ans=1;
	while(b)
	{
		if(b&1)
			ans=ans*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return ans;
}

int main()
{
#ifndef ONLINE_JUDGE
//	freopen("input.txt","r",stdin);
//	freopen("output.txt","w",stdout);
#endif
//	ios::sync_with_stdio(false);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		LL ans=0;
		if(i==n)
			ans=10;
		if(i<n)//在两头的情况
			ans=(ans+10*9*2*q_pow(10,n-i-1))%mod;
		if(i<n-1)//不在两头的情况
			ans=(ans+10*(n-i-1)*9*9*q_pow(10,n-i-2))%mod;
		printf("%lld ",ans);
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
    return 0;
}
发布了700 篇原创文章 · 获赞 29 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/105068793