Gym - 102394I Interesting Permutation【解题思路】

本文解析了有趣的排列问题Gym-102394IInterestingPermutation,涉及生成特定序列并计算满足条件的不同排列数量。关键在于理解最大值、最小值更新对排列的影响,以及如何通过数学逻辑求解。
摘要由CSDN通过智能技术生成

Gym - 102394I Interesting Permutation

题目+样例

DreamGrid has an interesting permutation of 1,2,…,n denoted by a1,a2,…,an. He generates three sequences f, g and h, all of length n, according to the permutation a in the way described below:

For each 1≤i≤n, fi=max{a1,a2,…,ai};
For each 1≤i≤n, gi=min{a1,a2,…,ai};
For each 1≤i≤n, hi=fi−gi.
BaoBao has just found the sequence hh DreamGrid generates and decides to restore the original permutation. Given the sequence h, please help BaoBao calculate the number of different permutations that can generate the sequence h. As the answer may be quite large, print the answer modulo 1e9+7.

Input
The input contains multiple cases. The first line of the input contains a single integer T (1≤T≤20000), the number of cases.

For each case, the first line of the input contains a single integer n (1≤n≤1e5), the length of the permutation as well as the sequences. The second line contains n integers h1,h2,…,hn
(1≤i≤n,0≤hi≤1e9).

It’s guaranteed that the sum of n over all cases does not exceed 2⋅1e6.

Output
For each case, print a single line containing a single integer, the number of different permutations that can generate the given sequence h. Don’t forget to print the answer modulo 1e9+7.

Input

3
3
0 2 2
3
0 1 2
3
0 2 3

Output

2
4
0

解题思路

开始做这个题目的时候,我以为是规律题目,赛后看了题解才知道好家伙,思维+数学
首先题目的大意就是,有一串1-n的数字a1-an(不会重复),然后告诉你maxi是从第一个数字到第i个数字中最大的那个,mini同理;之后hi是1-i中maxi-mini之差
现在告诉你这串数字有n长,也给出每一个hi的值,问满足这种情况的种类数有多少

首先我们可以了解到,i=1的时候必为0,因为最大最小是a1的本身;然后i=n的时候hn必为n-1,因为当前是整个区间,最大是n最小是1;然后可以分析到对于每一个hi必不可能大于n-1。
然后对于整体来说,hi 从0-n是递增得的,要么hi-1<hi 要么就hi-1 ==hi ,所以不满足上面的任何一种情况都是不可能的
对于给出来的h1-hn 出现hi-1 ==hi 说明当前ai值不会更新当前1-i区间内的最大最小值,也就是所ai取值在min到max之间,对于ai这个空我可以放入min到max之间的任何数字;当出现hi-1<hi说明ai此时要么更新了max的值要么更新了min的值,因此两种情况,在更新min or max 的同时也为我们遇到hi-1 ==hi情况扩充了更多的数字

最后得出的关键信息
ans是总和 ,cnt是可选择的个数

当 hi-1 ==hi
ans*=cnt;cnt–;

当 hi-1<hi
ans*=2;
cnt+=h[i]-h[i-1]-1;

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>

using namespace std;
#define ll long long
#define N 2000001
const ll mod= 1e9+7;

ll h[N];
int main ()
{
	ll t;
	scanf ("%lld",&t);
	while (t--)
	{
		bool flag=0;
		ll n,ans,cnt;
		scanf ("%lld",&n);
		for (ll i=0;i<n;i++)
		{
			scanf ("%lld",&h[i]);
			if (i==0&&h[i]!=0)flag=1;
			if (i>0&&h[i]<h[i-1])flag=1;
			if (h[i]>n-1)flag=1;
		}
		if (flag)
		{
			printf ("0\n");
			continue;
		}
		ans=1;//总和
		cnt=0;//空位数
		for (ll i=1;i<n;i++)
		{
			if (h[i]==h[i-1])
			{
				/*
				相等所以a[i]在max和min之间的数,从可选的数选一个
				排列问题
				*/
				ans=ans*cnt%mod;
				cnt=(cnt-1)%mod;
			}
			else
			{
				/*
				最大or最小更新,可选数扩充
				有两种情况max更新or最小更新
				所以ans*2
				*/
				cnt=(cnt+h[i]-h[i-1]-1)%mod;
				ans=ans*2%mod;
			}
		}
		printf ("%lld\n",ans);
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个人心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值