原题网址
由于某些原因,这个网址会进不去…
题目描述
输入一个排列(长度小于 50 50 50),输出它是第几个排列。第一个排列为 0 0 0。
格式
输入格式
输入一个排列。
输出格式
输出它的编码(从 0 0 0开始计数)。
样例
输入样例
3 2 1 4
输出样例
15
解题思路
由于本人太懒比赛时间有限,我尝试使用了while(cin>>a[i])
。结果——成功了!
这题我没想到得用高精,然后——我只得了30分。
此外,本题还得用康拓展开。
(作者注:为什么编码I用的康拓逆展开,编码II却用的康拓展开?)
Code
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<cstring>
#include<string>
#include<map>
#include<queue>
#define maxn 10000
using namespace std;
int ans[maxn + 1], a[maxn + 1], used[maxn + 1], n, s[maxn + 1]; // 所有高精计算答案都放在s里
void init() // 在此执行预处理
{
int i = 1;
while (cin>>a[i]) i ++;
n = i - 1;
}
void addd(int x[], int b) // 高精加单精
{
int g = 0;
for (int i = maxn; i >= 1; i --)
{
int q = x[i] + b % 10 + g;
s[i] = q % 10;
g = q / 10;
b /= 10;
}
}
void addf(int x[], int y[]) // 高精加高精
{
int g = 0;
for (int i = maxn; i >= 1; i --)
{
int q = x[i] + y[i] + g;
s[i] = q % 10;
g = q / 10;
}
}
void muld(int x[], int b) // 高精乘单精
{
int g = 0;
for (int i = maxn; i >= 1; i --)
{
int q = x[i] * b + g;
s[i] = q % 10;
g = q / 10;
}
}
void mulf(int x[], int y[]) // 高精乘高精
{
for (int i = maxn; i >= 1; i --)
{
int g = 0;
for (int j = maxn; j >= 1; j --)
{
int q = x[i] * y[j] + g;
s[i - j + 1] += q % 10;
g = q / 10;
}
}
int g = 0;
for (int i = maxn; i >= 1; i --)
{
s[i] += g;
g = s[i] / 10;
s[i] %= 10;
}
}
void jiec(int m) // 阶乘
{
memset(s, 0, sizeof(s));
s[maxn] = 1;
for (int i = 2; i <= m; i ++) muld(s, i);
}
void comp() // 康拓展开
{
for (int i = 1; i <= n; i ++)
{
used[a[i]] = 1;
int q = 0;
for (int j = 1; j < a[i]; j ++) if (!used[j]) q ++;
jiec(n - i);
muld(s, q);
addf(s, ans);
memcpy(ans, s, sizeof(s));
}
addd(ans, 1);
memcpy(ans, s, sizeof(s));
}
void oput() // 在此输出总结果
{
int ok = 0;
for (int i = 1; i <= maxn; i ++)
{
if (!ok && ans[i]) ok ++;
if (ok) cout<<ans[i];
}
if (!ok) cout<<0;
}
int main()
{
init();
comp();
oput();
return 0;
}
大功告成 ∼ \sim ∼