1380.JAM计数法

原题链接

外网进不去

题目大意

有一个人,用小写英文字母计数,再这种计算法中,每个字母互不相同,而且从左到右都是严格递增的,每次还规定能够使用一个范围的字母,规定了长度。题目将会给我们 s s s t t t w ( s ≤ t ≤ 26 , 2 ≤ w ≤ t − s ) w(s\le t\le 26,2\le w\le t-s) w(st26,2wts) n n n,分别代表字母开始位置,结束位置,数字长度和目前数字,要求往后输出五个连续的数字,如果没有,则尽量多输出。

解题思路

这一题虽说是排列,但却是以组合的方式解题。先来介绍一下组合(非搜索版):
原题链接:外网进不去
首先,定义一个变量 j j j,从最后开始,找到第一个不是从 n n n开始的连续递减序列里的末尾开始的,然后,再把 a [ j ] + + a[j]++ a[j]++,并在此基础上 a [ i ] = a [ i − 1 ] + 1 a[i]=a[i-1]+1 a[i]=a[i1]+1,直到序列变为:
n − l e n t h + 1 , n − l e n t h + 2 , . . . , n − 2 , n − 1 , n n-lenth+1,n-lenth+2,...,n-2,n-1,n nlenth+1,nlenth+2,...,n2,n1,n
代码结束。
如:
要求使用从 1 ∼ 5 1\sim 5 15这五个数中选 3 3 3个组合:
初始: 1 , 2 , 3 1,2,3 123
计算结束后, j = 3 j=3 j=3,得 1 , 2 , 4 1,2,4 124
再次计算结束后, j = 3 j=3 j=3,得 1 , 2 , 5 1,2,5 125
又一次计算结束后, j = 2 j=2 j=2,得 1 , 3 , 4 1,3,4 134
接着, j = 3 j=3 j=3,得 1 , 3 , 5 1,3,5 135
然后, j = 2 j=2 j=2,得 1 , 4 , 5 1,4,5 145
……
最后, j = 2 j=2 j=2,得 3 , 4 , 5 3,4,5 345
接着, j = 1 j=1 j=1,结束;
代码实现:

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
long long n,a[100],fact[100],m;
int main()
{
    
    
	cin>>n>>m;
	for(long long i=1;i<=m;i++)
		a[i]=i;
	while(true){
    
    
		for(int j=1;j<=m;j++)
			cout<<a[j];
		cout<<endl; 
		long long i=m;
		while(i>0&&a[i]==n-m+i)
			i--;
		a[i]++;
		for(long long l=i+1;l<=m;l++)
			a[l]=a[l-1]+1;
		if(i==0)
			break;
	}
}

其实,这一题也十分类似。我们可以以题目所给的数据为初始,先将末尾加一,如果超界,再往前试。由于要求严格递增,就算是当前没有超界,结尾也有可能超界。所以如果想要判断超界,那么就得计算出结尾,并且判断是否超界。结尾公式不难推,仔细想想,就可以得到 a ( n ) = a ( j ) + l e n t h − j a(n)=a(j)+lenth-j a(n)=a(j)+lenthj的计算公式,但如果运行到了这里,就说明前面一直超界,所以这个位置应该加一,所以正确判断出界的公式应为: a ( j ) + l e n t h − j + 1 a(j)+lenth-j+1 a(j)+lenthj+1,如果会超界,那 j = j − 1 j=j-1 j=j1。一直找到一个不超界的地方,如果是 1 1 1,程序就结束里,如果不是,就把这个位置加一,由于要求严格递增,所以最接近上一个数的数应该是每一位都在这个位的基础上加一( a ( i ) = a ( i − 1 ) + 1 a(i)=a(i-1)+1 a(i)=a(i1)+1)。

2 10 5
bdfij

首先 j = 3 j=3 j=3,可得到: b d g h i bdghi bdghi
接着 j = 5 j=5 j=5,可得到: b d g h j bdghj bdghj
然后 j = 4 j=4 j=4,可得到: b d g i j bdgij bdgij
再接着 j = 3 j=3 j=3,可得到: b d h i j bdhij bdhij
最后 j = 2 j=2 j=2,可得到: b e f g h befgh befgh
输出满了五个,程序结束。

代码实现:

#include<bits/stdc++.h>
using namespace std;
long long n,m,t;
char a[100];
int main()
{
    
    
	cin>>n>>m>>t;
	for(int i=1;i<=t;i++)
		cin>>a[i];
	for(int k=1;k<=5;k++){
    
    //之后五个
		int j=t;
		while(j>0&&a[j]-'a'+t-j+1>=m)//枚举j
			j--;
		if(j==0)//结束条件,没有更多
			break;//结束
		a[j]++;//在当前位置加一
		for(int i=j+1;i<=t;i++)
			a[i]=a[i-1]+1;//在a[j]的基础上,a[i]=a[i-1]+1
		for(int i=1;i<=t;i++)
			cout<<a[i];//输出
		cout<<endl;
	}
}

样例

输入

2 10 5
bdfij

输出

bdghi
bdghj
bdgij
bdhij
befgh

おすすめ

転載: blog.csdn.net/weixin_41247488/article/details/119793296