题解 P1246

有点坑的一道组合题。


解题思路:

首先对于每一个字符串,长度比其小的一定比其小,这一块的总贡献是 ∑ i − 1 l e n − 1 C 26 i \sum_{i-1}^{len-1}C_{26}^i i1len1C26i

然后是长度相等的,当确定前 i i i 位相等,当前位(也就是 i + 1 i+1 i+1 位,这里与程序实现有所不同)的字符为 j j j (转26进制,同样与程序实现不同)时,产生的方案贡献为 C 26 − j − 1 l e n − i − 1 C_{26-j-1}^{len-i-1} C26j1leni1,这里需要枚举累加。


代码:

#include<cstdio>
#include<string>
#include<iostream>
using namespace std;
string a;
int ans;
int C(int m,int n){
	if(m==0)return 1;
	int ans=1;
	for(int i=n-m+1;i<=n;i++)
	ans*=i;
	for(int i=1;i<=m;i++)
	ans/=i;
	return ans;
}
int main(){
	cin>>a;
	for(int i=0;i<a.length();i++)
	if(a[i]<=a[i-1]){
		printf("0\n");
		return 0;
	}
	for(int i=1;i<a.length();i++)
	ans+=C(i,26);
	for(int i=0;i<a.length();i++){
		for(int j=(i==0?1:a[i-1]-'a'+2);j<a[i]-'a'+1;j++)
		ans+=C(a.length()-i-1,26-j);
	}
	printf("%d",ans+1);
	return 0;
}

反思:

本身不是一道非常难的组合题,但是还是做了好长时间,中途还 WA 了一发,这一块要多练练。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值