Codeforces 466D Increase Sequence【思维】好题~

本文介绍了一个算法问题,探讨如何计算使序列中所有元素变为特定值h的不同方式的数量,并提供了实现思路及AC代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

D. Increase Sequence
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Peter has a sequence of integers a1, a2, ..., an. Peter wants all numbers in the sequence to equal h. He can perform the operation of "adding one on the segment [l, r]": add one to all elements of the sequence with indices from l to r (inclusive). At that, Peter never chooses any element as the beginning of the segment twice. Similarly, Peter never chooses any element as the end of the segment twice. In other words, for any two segments [l1, r1] and [l2, r2], where Peter added one, the following inequalities hold: l1 ≠ l2 and r1 ≠ r2.

How many distinct ways are there to make all numbers in the sequence equal h? Print this number of ways modulo 1000000007 (109 + 7). Two ways are considered distinct if one of them has a segment that isn't in the other way.

Input

The first line contains two integers n, h (1 ≤ n, h ≤ 2000). The next line contains n integers a1, a2, ..., an (0 ≤ ai ≤ 2000).

Output

Print a single integer — the answer to the problem modulo 1000000007 (109 + 7).

Examples
Input
3 2
1 1 1
Output
4
Input
5 1
1 1 1 1 1
Output
1
Input
4 3
3 2 1 1
Output
0

题目大意:

让你找一共有多少种合法解的方案。

每一种合法解需要:

将序列中每一个元素最终都变成h.

每一次操作可以选择一个区间【l,r】,使得区间内所有元素+1.

要求操作过程中,对于一个位子i,不能同时作为两个区间的l,也不能同时作为两个区间的r.换句话说,一个位子i,要么是一个区间的l,要么是一个区间的r,或者什么都不是、


思路:


我们首先处理出每个位子需要被多少个区间覆盖才能变成h。即a【i】=h-a【i】;

同时设定b【i】=a【i】-a【i-1】;

如果b【i】==1,很显然,此时需要多设立一个l在位子i处。那么我们过程维护一下需要设立l的个数cnt.那么b【i】==1的时候,cnt++.

如果b【i】==0,很显然,位子i可能有两种情况:

①这个位子什么都没有。

②这个位子既有一个l,也有一个r.那么对于这个位子i,如果有r的话,我们可以对之前的cnt个l进行匹配,当然也可以对当前位子的这个l进行匹配,那么有:ans*=(cnt+1);

如果b【i】==-1,很显然,此时需要多设立一个r在位子i处 ,那么我们要在之前的cnt个l中选择一个和它进行匹配,那么有:ans*=cnt.同时cnt--;

如果b【i】!=0&&b【i】!=-1&&b【i】!=1,那么显然无解。


Ac代码:

#include<stdio.h>
#include<string.h>
using namespace std;
#define mod 1000000007
#define ll __int64
int a[2500];
int b[2500];
int main()
{
    int n,h;
    while(~scanf("%d%d",&n,&h))
    {
        memset(a,0,sizeof(a));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            a[i]=h-a[i];
        }
        for(int i=1;i<=n+1;i++)
        {
            b[i]=a[i]-a[i-1];
        }
        ll cnt=0;
        ll ans=1;
        for(int i=1;i<=n+1;i++)
        {
            if(b[i]==1)
            {
                cnt++;
            }
            else if(b[i]==0)
            {
                ans*=(cnt+1);
            }
            else if(b[i]==-1)
            {
                ans*=(cnt);
                cnt--;
            }
            else
            {
                printf("0\n");
                return 0;
            }
            ans%=mod;
        }
        printf("%I64d\n",ans);
    }
}










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值