hihocoder1579

此题应该算是开荒题了吧。。。

主要注意对于一个后缀的排名显然第一位是最重要的,然后对于两个不同的后缀第一位什么时候能相同呢?就是如果a<b那么在a后的后缀h,和在b后的后缀k依然是h<k的话那么就a=b就是可能的如果h>k那么必然有a<b

这样更具题目给的条件我们就把此题转化成了一个组合数学问题,

对于样例

第一个级别对应位置4,位置5的级别是4

第二级别对应位置3,位置4的级别是1

因为4>1,所以第一级别的字母一定是比第二级别的字母小的

然后这样一个一个推下去。看哪些相邻级别的字母能相同

然后问题就是一个插板问题了

首先一定会有总共25个版,每个版对应一个字母级别从左到右是a b c d .....,然后前面我们算出了一定会在某些地方插bannum个版,这些版是位置不变而且数目也不变的,就只能插在出现断层的字母之间,还剩下25-bannum个版,我们让这25-bannum个版插进n个字母中这应该是个很简单的组合问题了。插了这些版再插固定版所以答案就是

C(25-bannum                                                                                                                                                                                                                                                                     n+25-bannum)

然后要写高精度。。。

开荒+高精度第一次写。。。所以我已经wa到麻木了。。。。。。然后终于过了。。。注意c(0,n)这个要特判对于很可能错

写得很多,大多数都是没用的,不过我只是拿来研究高精度了。。。其实还有很多地方需要完善,以后来弥补。。。

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
typedef long long ll;
const ll base = 1000000000;
const ll poww[10] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
struct Big_int
{
	ll num[8000];
	int cnt;
	friend istream& operator>>(istream &in, Big_int &c)
	{
		char s[3000];
		for (int i = 0; i < 3000; i++)
			c.num[i] = 0;
		scanf("%s", s+1);
		int len = strlen(s+1);
		c.cnt = (len-1)/ 9 + 1;
		for (int i = 1; i <= len; i++)
		{
			c.num[(len - i) / 9 + 1] += (s[i] - '0')*poww[(len - i) % 9];
		}
		return in;
	}
	Big_int& operator=(ll a)
	{
		for (int i = 0; i <3000; i++)
			num[i] = 0;
		int tot = 1;
		while (a)
		{
			num[tot] = a%base;
			a /= base;
			tot++;
		}
		cnt = tot - 1;
		return *this;
	}
	Big_int& operator*=(ll a)
	{
		Big_int c;
		c = 0;
		for (int i = 1; i <= cnt; i++)
		{
			c.num[i]+= num[i] * a;
			if (c.num[i]>base)
				c.num[i + 1] += c.num[i] / base,
				c.num[i] %= base;
		}
		if (c.num[cnt + 1])
			cnt++;
		while (c.num[cnt] > base)
		{
			c.num[cnt + 1] += c.num[cnt] / base,
				c.num[cnt] %= base;
			cnt++;
		}
		for (int i = 1; i <= cnt; i++)
			num[i] = c.num[i];
		return *this;
	}
	Big_int& operator/=(ll a)
	{
		for (int i = cnt; i >= 1; i--)
		{
			if (i - 1)
			{
				num[i - 1] += (num[i] % a)*base;
			}
			num[i] /= a;
		}
		while (num[cnt] == 0)
			cnt--;
		return *this;
	}
	friend bool operator>(Big_int &a, Big_int &b)
	{
		if (a.cnt == b.cnt)
		{
			for (int i = a.cnt; i >= 1; i--)
			{
				if (a.num[i] > b.num[i])
					return true;
			}
			return false;
		}
		else
		{
			return a.cnt > b.cnt;
		}
	}
	friend ostream& operator<<(ostream &out, Big_int &c)
	{
		if (c.num[0] == 1)
			printf("-");
		printf("%lld", c.num[c.cnt]);
		for (int i = c.cnt - 1; i >= 1; i--)
		{
			printf("%09lld", c.num[i]);
		}
		return out;
	}
};
Big_int operator*(Big_int &a, Big_int &b)
{
	Big_int c;
	c = 0;
	if (b > a)
		swap(a, b);
	int get1 = 0, get2 = 0;
	for (int i = 1; i <= b.cnt; i++)
	{
		int get1 = 0, get2 = 0;
		for (int j = 1; j <= a.cnt+1; j++)
		{
			get2 = (a.num[j] * b.num[i]) / base;
			c.num[i + j - 1] += ((a.num[j] * b.num[i]) % base)+get1;
			if (c.num[i + j - 1] >=base)
			{
				get2 += c.num[i + j - 1] / base;
				c.num[i + j - 1] %= base;
			}
			get1 = get2;
		}
	}
	if (c.num[a.cnt + b.cnt])
		c.cnt = a.cnt + b.cnt;
	else
		c.cnt = a.cnt + b.cnt-1;
	while (c.num[c.cnt] > base)
	{
		c.num[c.cnt + 1] += c.num[c.cnt] / base;
		c.num[c.cnt] %= base;
		c.cnt++;
	}
	return c;
}
Big_int& operator-(Big_int &a, Big_int &b)
{
	if (b > a)
	{
		swap(a, b);
		a.num[0] = 1;
	}
	for (int i = 1; i <= b.cnt; i++)
	{
		if (a.num[i] < b.num[i])
		{
			a.num[i + 1]--;
			a.num[i] += base;
		}
		a.num[i] -= b.num[i];
	}
	return a;
}
Big_int& operator+(Big_int &a, Big_int &b)
{
	if (b > a)
		swap(a, b);
	for (int i = 1; i <= b.cnt; i++)
	{
		a.num[i] += b.num[i];
		if (a.num[i] >= base)
		{
			a.num[i + 1] += (a.num[i] / base);
			a.num[i] %= base;
		}
	}
	if (a.num[a.cnt + 1])
		a.cnt++;
	return a;
}
int n, t;
void solve(int bannum)
{
	ll all = n + 25- bannum;
	ll num = 25 - bannum;
	//ll num2 = all - num;
	//if (num > num2)
	//	swap(num, num2);
	Big_int a ;
	a = all;
	all--;
	for (int i = 2; i <= num; i++)
	{
		a *= all;
		all--;
	}
	//cout << a << endl;
	if (bannum == 25)
	{
		printf("1\n");
	}
	else
	{
		for (int i = 1; i <= num; i++)
			a /= i;
		cout << a << endl;
	}
}
int a[100020], pos[100020];
int main()
{
	/*ll b = 31 * 30 * 29 * 28 * 27 * 26;
	b /= 720;
	cout << b << endl;
	Big_int aa;
	aa = 1;
	for (int i = 31; i >= 26; i--)
		aa *= i;
	aa /= 720;
	cout << aa << endl;*/
	int t;
	scanf("%d", &t);;
	while (t--)
	{
		scanf("%d", &n);
		for (int i = 1; i <= n; i++)
			scanf("%d", &a[i]);
		for (int i = 1; i <= n; i++)
			pos[a[i]] = i;
		int bannum = 0;
		for (int i = 2; i <= n; i++)
			if (pos[a[i - 1] + 1] > pos[a[i] + 1])
				bannum++;
		//cout << bannum << endl;
		if (bannum > 25)
			printf("0\n");
		else
			solve(bannum);
	}
	return 0;
}

指针版高精度。其实高精还是适合用指针写,不过不好调试。。。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll base = 100;
const ll bl = 2;
ll poww[10] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
struct Big_int
{
	ll *num;
	int cnt;
	Big_int()
	{
		
	}
	~Big_int()
	{
		delete []num;
	}
	Big_int(ll get,int kind)
	{
		if (kind == 1)
			num = new ll[80000];
		if (kind == 2)
			num = new ll[8];
		int i;
		for ( i = 1; get; i++)
		{
			num[i] = get%base;
			get /= base;
		}
		cnt = i-1;
	}
	friend istream& operator>>(istream &in, Big_int *c)
	{
		static char s[72000];
		scanf("%s", s+1);
		int len = strlen(s+1);
		c->num = new ll[9*len];
		c->cnt = len / bl + 1;
		for (int i = 0; i <= c->cnt; i++)
			c->num[i] = 0;
		for (int i = 1; i <= len; i++)
		{
			c->num[(len - i) / bl + 1] += (s[i] - '0')*poww[(len - i) % bl];
		}
		if (c->num[c->cnt] == 0)
			c->cnt--;
		return in;
	}
	Big_int& operator*=(ll a)
	{
		ll get1 = 0, get2 = 0;
		for (int i = 1; i <= cnt+1; i++)
		{
			if (i == cnt + 1)
				num[i] = 0;
			get1 = (num[i] * a) / base;
			num[i] = (num[i] * a) % base+get2;
			get2 = get1;
			if (num[i] >= base&&i!=cnt+1)
			{
				get2 += num[i] / base;
				num[i] %= base;
			}
			
		}
		if (num[cnt + 1])
			cnt++;
		while (num[cnt] > base)
		{
			num[cnt + 1] = 0;
			num[cnt + 1] += num[cnt] / base;
			num[cnt] %= base;
			cnt++;
		}
		return *this;
	}
	friend ostream& operator<<(ostream &out, Big_int *c)
	{
		printf("%lld", c->num[c->cnt]);
		for (int i = c->cnt - 1; i >= 1; i--)
		{
			printf("%02lld", c->num[i]);
		}
		return out;
	}
};
Big_int *qq,*pp,*lgl;
Big_int kk;
int main()
{
	qq = new Big_int(20,1);
	pp = new Big_int(20,1);
	lgl = new Big_int(20, 1);
	return 0;
}*/



再存一个自己写的高精度

//高精度
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
typedef long long ll;
const ll base = 1000000000;
const ll poww[10] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
struct Big_int
{
	ll num[8000];
	int cnt;
	friend istream& operator>>(istream &in, Big_int &c)
	{
		char s[3000];
		for (int i = 0; i < 3000; i++)
			c.num[i] = 0;
		scanf("%s", s+1);
		int len = strlen(s+1);
		c.cnt = (len-1)/ 9 + 1;
		for (int i = 1; i <= len; i++)
		{
			c.num[(len - i) / 9 + 1] += (s[i] - '0')*poww[(len - i) % 9];
		}
		return in;
	}
	Big_int& operator=(ll a)
	{
		for (int i = 0; i <3000; i++)
			num[i] = 0;
		int tot = 1;
		while (a)
		{
			num[tot] = a%base;
			a /= base;
			tot++;
		}
		cnt = tot - 1;
		return *this;
	}
	Big_int& operator*=(ll a)
	{
		Big_int c;
		c = 0;
		for (int i = 1; i <= cnt; i++)
		{
			c.num[i]+= num[i] * a;
			if (c.num[i]>base)
				c.num[i + 1] += c.num[i] / base,
				c.num[i] %= base;
		}
		if (c.num[cnt + 1])
			cnt++;
		while (c.num[cnt] > base)
		{
			c.num[cnt + 1] += c.num[cnt] / base,
				c.num[cnt] %= base;
			cnt++;
		}
		for (int i = 1; i <= cnt; i++)
			num[i] = c.num[i];
		return *this;
	}
	Big_int& operator/=(ll a)
	{
		for (int i = cnt; i >= 1; i--)
		{
			if (i - 1)
			{
				num[i - 1] += (num[i] % a)*base;
			}
			num[i] /= a;
		}
		while (num[cnt] == 0)
			cnt--;
		return *this;
	}
	friend bool operator>(Big_int &a, Big_int &b)
	{
		if (a.cnt == b.cnt)
		{
			for (int i = a.cnt; i >= 1; i--)
			{
				if (a.num[i] > b.num[i])
					return true;
			}
			return false;
		}
		else
		{
			return a.cnt > b.cnt;
		}
	}
	friend ostream& operator<<(ostream &out, Big_int &c)
	{
		if (c.num[0] == 1)
			printf("-");
		printf("%lld", c.num[c.cnt]);
		for (int i = c.cnt - 1; i >= 1; i--)
		{
			printf("%09lld", c.num[i]);
		}
		return out;
	}
};
Big_int operator*(Big_int &a, Big_int &b)
{
	Big_int c;
	c = 0;
	if (b > a)
		swap(a, b);
	int get1 = 0, get2 = 0;
	for (int i = 1; i <= b.cnt; i++)
	{
		int get1 = 0, get2 = 0;
		for (int j = 1; j <= a.cnt+1; j++)
		{
			get2 = (a.num[j] * b.num[i]) / base;
			c.num[i + j - 1] += ((a.num[j] * b.num[i]) % base)+get1;
			if (c.num[i + j - 1] >=base)
			{
				get2 += c.num[i + j - 1] / base;
				c.num[i + j - 1] %= base;
			}
			get1 = get2;
		}
	}
	if (c.num[a.cnt + b.cnt])
		c.cnt = a.cnt + b.cnt;
	else
		c.cnt = a.cnt + b.cnt-1;
	while (c.num[c.cnt] > base)
	{
		c.num[c.cnt + 1] += c.num[c.cnt] / base;
		c.num[c.cnt] %= base;
		c.cnt++;
	}
	return c;
}
Big_int& operator-(Big_int &a, Big_int &b)
{
	if (b > a)
	{
		swap(a, b);
		a.num[0] = 1;
	}
	for (int i = 1; i <= b.cnt; i++)
	{
		if (a.num[i] < b.num[i])
		{
			a.num[i + 1]--;
			a.num[i] += base;
		}
		a.num[i] -= b.num[i];
	}
	return a;
}
Big_int& operator+(Big_int &a, Big_int &b)
{
	if (b > a)
		swap(a, b);
	for (int i = 1; i <= b.cnt; i++)
	{
		a.num[i] += b.num[i];
		if (a.num[i] >= base)
		{
			a.num[i + 1] += (a.num[i] / base);
			a.num[i] %= base;
		}
	}
	if (a.num[a.cnt + 1])
		a.cnt++;
	return a;
}
int n, t;
void solve(int bannum)
{
	ll all = n + 25- bannum;
	ll num = 25 - bannum;
	//ll num2 = all - num;
	//if (num > num2)
	//	swap(num, num2);
	Big_int a ;
	a = all;
	all--;
	for (int i = 2; i <= num; i++)
	{
		a *= all;
		all--;
	}
	//cout << a << endl;
	if (bannum == 25)
	{
		printf("1\n");
	}
	else
	{
		for (int i = 1; i <= num; i++)
			a /= i;
		cout << a << endl;
	}
}
int a[100020], pos[100020];
int main()
{
	/*ll b = 31 * 30 * 29 * 28 * 27 * 26;
	b /= 720;
	cout << b << endl;
	Big_int aa;
	aa = 1;
	for (int i = 31; i >= 26; i--)
		aa *= i;
	aa /= 720;
	cout << aa << endl;*/
	int t;
	scanf("%d", &t);;
	while (t--)
	{
		scanf("%d", &n);
		for (int i = 1; i <= n; i++)
			scanf("%d", &a[i]);
		for (int i = 1; i <= n; i++)
			pos[a[i]] = i;
		int bannum = 0;
		for (int i = 2; i <= n; i++)
			if (pos[a[i - 1] + 1] > pos[a[i] + 1])
				bannum++;
		//cout << bannum << endl;
		if (bannum > 25)
			printf("0\n");
		else
			solve(bannum);
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值