Gym - 102394I Interesting Permutation(思维)

题目链接:https://vjudge.net/contest/398708#problem/I

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 h 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 10^9+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≤105), the length of the permutation as well as the sequences. The second line contains n integers h1,h2,…,hn (1≤i≤n,0≤hi≤10^9).

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

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 10^9+7.

Input

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

Output

2
4
0

Note
For the first sample case, permutations {1,3,2} and {3,1,2} can both generate the given sequence.

For the second sample case, permutations {1,2,3}, {2,1,3}, {2,3,1} and {3,2,1} can generate the given sequence.

翻译:

原排列p为a1,a2,…,an
f i = m a x ( a 1 , a 2 , … , a i ) , g i = m i n ( a 1 , a 2 , … , a i ) fi= max (a1,a2,…,ai),gi=min(a1,a2,…,ai ) fi=max(a1,a2,,ai)gi=min(a1,a2,,ai) h i = f i − g i hi=fi−gi hi=figi,现给出序列h,求满足h的P的个数

分析:
h数列只能是递增的,且第一个数必为0,最大值为n-1

对于一个递增的数列只有两种情况:
1.h[i]=h[i-1]
2.h[i]>h[i-1]

对应第二种情况是:最大值有更新或最小值有更新,对应的结果*2
对应第一种情况:a[i]的取值范围为:
m i n ( a 1 , a 2 , , , , , , a i − 1 ) < = a [ i ] < = m a x ( a 1 , a 2 , , , , , , a i − 1 ) min(a_1,a_2,,,,,,a_{i-1})<=a[i]<=max(a_1,a_2,,,,,,a_{i-1}) min(a1,a2,,,,,,ai1)<=a[i]<=max(a1,a2,,,,,,ai1)
定义大于等于min,小于等于max的数为中间数
假设中间数的个数为num,对应的结果*num

当h[i]>h[i-1]时,h[i]-h[i-1]-1为加上h[i]后新增的中间数的个数

完整代码:

#include<cstdio>
#include<cstring>
#include<math.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=1e5+10;
const int mod=1e9+7;
int n;
LL height[N];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=0; i<n; i++)
            scanf("%lld",&height[i]);
        bool book=false;
        for(int i=1; i<n; i++)
        {
            if(height[i-1]>height[i]||height[i]>=n)
            {
                book=true;
                break;
            }
        }
        if(height[0]!=0)
            book=true;
        if(book)
            printf("0\n");
        else
        {
            LL sum=1,ans=0;
            for(int i=1; i<n; i++)
            {
                if(height[i]>height[i-1])
                {
                    sum=(sum*2)%mod;
                    ans+=height[i]-height[i-1]-1;///新增的中间数
                }
                else
                {
                    sum=(sum*ans)%mod;
                    ans--;///用掉一个
                }
            }
            printf("%lld\n",sum%mod);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

zaiyang遇见

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

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

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

打赏作者

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

抵扣说明:

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

余额充值