编码
概述
给你一个排列,求序号(如1 2 3 4为1,5 4 3 2 1为120)
输入样例
3 2 1 4
输出样例
15
思路
就是一个康托展开,但是要加高精度,而且康托展开是从0开始编,所以错了3次555
康托展开:
公式如下:
s
=
a
[
n
]
∗
(
n
−
1
)
!
+
a
[
n
−
1
]
∗
(
n
−
2
)
!
…
…
a
[
1
]
∗
(
n
−
n
)
!
s=a[n]*(n-1)!+a[n-1]*(n-2)!……a[1]*(n-n)!
s=a[n]∗(n−1)!+a[n−1]∗(n−2)!……a[1]∗(n−n)!
上正确代码:
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<map>
#include<string>
using namespace std;
bool b[60];
int a[60],n;
int q[1001],q2[1001];
string add(string a,string b)
{
memset(q,0,sizeof(q));
memset(q2,0,sizeof(q2));
for (int i=1;i<=a.size();i++) q[i]=a[a.size()-i]-'0';
for (int j=1;j<=b.size();j++) q2[j]=b[b.size()-j]-'0';
int s=0,g=0;
for (int i=1;i<=1000;i++)
{
s=q[i]+q2[i]+g;
q[i]=s%10;
g=s/10;
}
int i=1000;
while (i>1&&q[i]==0) i--;
string y="";
for (int j=i;j>=1;j--)
{
char x=q[j]+'0';
y+=x;
}
return y;
}
string divb(string x,int y)
{
string c1="";
unsigned long long u=0;
for (int i=0;i<x.size();i++)
{
u=u*10+x[i]-'0';
char x=u/y+'0';
c1+=x;
u%=y;
}
while (c1[0]=='0') c1.erase(0,1);
return c1;
}
string mul(string a,int b)
{
memset(q,0,sizeof(q));
for (int i=1;i<=a.size();i++) q[i]=a[a.size()-i]-'0';
int s=0,g=0;
for (int i=1;i<=1000;i++)
{
s=q[i]*b+g;
q[i]=s%10;
g=s/10;
}
int i=1000;
while (i>1&&q[i]==0) i--;
string y="";
for (int j=i;j>=1;j--)
{
char x=q[j]+'0';
y+=x;
}
return y;
}
int main()
{
string gy;
getline(cin,gy);
int u=0;
string s="1",ans="0";
for (int i=0;i<gy.size();i++)
{
if (gy[i]==' ')
{
a[++n]=u;
u=0;
}
else
{
u=u*10+gy[i]-'0';
}
}
a[++n]=u;
for (int i=1;i<=n;i++) s=mul(s,i);
for (int i=1;i<=n;i++)
{
u=0;
for (int j=1;j<a[i];j++)
{
if (b[j]==0) u++;
}
b[a[i]]=1;
s=divb(s,n-i+1);
ans=add(ans,mul(s,u));
}
cout<<add(ans,"1");
return 0;
}