【SSL】2021-08-17 1377.编码II

原题网址

由于某些原因,这个网址会进不去…

1377.编码II - 原题网址

题目描述

输入一个排列(长度小于 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值