Gym - 102394I Interesting Permutation
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;
}