题意;
从1~9之间顺序取N个数字,组成每位数不重复的所有可能的N位数,按从小到大的顺序进行编号,当输入其中的任何一个数M是,能找出该数对应的编号。如:当N = 3,M = 132时,则输出: [123(1), 132(2), 213(3), 231(4), 312(5), 321(6)]——> X = 2
Input
输入只有一行,两个正整数N和M(1 ≤ N ≤ 9,1 ≤ K ≤ 987654321),之间用一个空格分隔开。
Output
输出对应的编号X。
Sample Input
3 132
Sample Output
2
这类题 其实就是让我们来对数的全排列
首先简单的说一下思路: 例如 数字 3142 他前面一定有1和2 开头之后剩下三个数的全排列 也就是阶乘;所以一定会用到阶乘不妨就写一个阶乘函数,当然这个阶乘函数引入的不是这个位的位数 而是 这个位数-1的阶乘 。这一点应该很好理解。之后就来研究该怎么处理这个阶乘。 3的话,在它之前一定有1,2的全排也就是阶乘乘以二。 |
中间一点错误:一开始我是用这个数减一后来考虑到后面就不对了 1先跳过,看4 他要是按这种方法的话就是3种 可是他跟最后一位最多2个数字就2种情况 :42 , 24 ; |
正确思路 :找到逆序数也就是比他位数低,而且数值也比这位数小 像 3142 一样就是2*(3!)*0*(2!)*1*(1)=13; |
# include<stdio.h>
int solve(int num)
{
int sign=1,i;
for(i=1;i<=num;i++)
sign*=i;
return sign;
}
int main()
{
char str[20];
int n,sum=0,count=0,i,j;
scanf("%d %s",&n,str);
for(i=0;i<n-1;i++)
{
count=0;
for(j=i+1;j<n;j++)
if(str[j]<str[i])count++;//计算逆序数
sum+=count*solve(n-i-1);//后面可能出现的情况计算
}
printf("%d\n",sum+1);
return 0;
}
方法二: <mark>深搜</mark>
深搜这种方法也不用大说直接看代码吧。
#include<stdio.h>//深度搜索
# include<string.h>
int n,loop,vis[100],j,result[100],Count,sign;
char str[100];
void DFS(int step)
{
int i;
sign=0;
if(step==n+1)//结束
{
Count+=1;
for(i=1;i<=n;i++)
{
if(result[i]==str[i-1]-'0')//判断找得这个数是不是需要的那个数
sign+=1;
}
if(sign==n)//是这个数
loop=Count;//这就是那个数排序后的序号
return;
}
for(i=1;i<=n;i++)//从一看是dfs
{
if(!vis[i])
{
vis[i]=1;//标记这个数用过避免重复使用
result[step]=i;
DFS(step+1);
vis[i]=0;//还原
}
}
}
int main()
{
scanf("%d %s",&n,str);
memset(vis,0,sizeof(vis));
Count=0;
sign=0;
DFS(1);//从一开始dfs
printf("%d\n",loop);
return 0;
}
方法三:
这种方法其实是中用c++中的一种函数next_permutation和prev_permutation 现在还没大搞懂 ```cpp //第一种方法在algorithm里面有个next_permutation可以实现,排序道理是一样的 //如果把next_permutation换成prev_permutation,一开始赋值就应是倒序,如:321 # include # include # include using namespace std; int main() { int num,count=0,i; char str[20],s[20]; cin>>num>>str; for(i=0;i |
//换位的递归思想还不错,就是没按字典顺序来,仅供看思想
# include<iostream>
using namespace std;
char str[20];
int t,leap;
void Swap(int *a,int *b)//重视
{
int temp;
temp=*a;
*a=*b;
*b=temp;
}
void Array(int *s,int Count,int n)
{
if(leap)return;
if(Count==n)
{
t++;
int sign=0;
for(int i=0;i<=n;i++)
if(s[i]==str[i]-'0')sign++;
if(sign==n+1)
{
cout<<t<<endl;
leap=1;
}
return;
}
for(int i=Count;i<=n;i++)
{
Swap(&s[i],&s[Count]);
Array(s,Count+1,n);
Swap(&s[i],&s[Count]);
}
}
int main()
{
int s[20];
int num,i;
while(cin>>num>>str)
{
t=0;
leap=0;
for(i=0;i<num;i++)
s[i]=i+1;
Array(s,0,num-1);
}
return 0;
}
<mark>总结</mark> ;
遇到这类题往枚举,深搜上想好点,毕竟时间复杂度太大 最大8^8 这种好想点 ,再者就是找先规律。当然也不要每个题都能找得到规律,功夫不到家就是白忙活,所以,Fighting!!! |