列表

详情


NC200281. The Flower of Hope

描述

“是啊...我们一直以来累积的东西,并非全部白费,今后也是,只要我们不停下脚步,道路就会不断延伸...”

在火星的某个实验室里,摆放着许多蕴含能量的小晶块 (Cube Fragment),这些小晶块可以被融合在一起得到蕴含能量更多的大晶体,但是随意地融合会导致大晶体变得不稳定,研究员将晶块摆放一排,从左向右数第i个晶块具有a_i个单位的能量,他发现:

1. 融合两个能量依次为a和b的晶块后能够得到能量为a + b的晶块。
2. 放到一排后,只能融合相邻的晶块。
3. 晶块的能量无法超过m,如果某个晶块具有了能量t,则多余的能量会逸散掉,只剩下的能量,其中表示取模(取余)运算。
4. 融合后剩余能量不超过参与融合的所有晶块的能量之和的一半的晶体被认为是稳定的。

研究员想要知道有多少个不同的区间,满足将区间内所有晶块融合后得到的晶体是稳定的。
形式化地说,有一串长度为n的非负整数序列,有多少子区间的和值k对m取模后不大于。如果使用有序对来唯一表示每一个子区间,他希望知道有多少对有序对满足:
1. .
2. .
两个子区间被认为是不同的,当且仅当它们至少存在一个不同的区间端点。即对于两个区间,如果有成立,则认为这两个区间是不同的。


输入描述

第一行为两个正整数n和m,含义如题目描述,之间使用一个空格符分隔。
第二行为n个非负整数,其中第i个输入的整数记作a_i,相邻整数之间使用一个空格符分隔。

数据规范:
* .
* .
* .

输出描述

输出一个正整数,表示满足条件的子区间数目。

示例1

输入:

5 2
1 1 1 1 1

输出:

10

说明:

任意长度大于1的子区间都满足条件。

示例2

输入:

5 2
2 2 2 2 2

输出:

15

说明:

所有子区间都满足条件。

示例3

输入:

3 10
1 2 3

输出:

0

说明:

所有的子区间都不满足条件。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 23ms, 内存消耗: 1528K, 提交时间: 2020-06-14 13:26:37

/*================================================================
*
*   创 建 者: badcw
*   创建日期: 2020/6/14
*
================================================================*/
#include <bits/stdc++.h>

#define ll long long
using namespace std;

const int maxn = 1e5+50;
const int mod = 1e9+7;
ll qp(ll a, ll n, ll mod = ::mod) {
    ll res = 1;
    while (n > 0) {
        if (n & 1) res = res * a % mod;
        a = a * a % mod;
        n >>= 1;
    }
    return res;
}

int n, m;
int a[maxn];
ll pre[maxn];

int main(int argc, char* argv[]) {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
        pre[i] = pre[i - 1] + a[i];
    }
    ll res = 0;
    for (int i = 1; i <= n; ++i) {
        res += upper_bound(pre, pre + i, pre[i] - m) - pre;
    }
    printf("%lld\n", res);
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 30ms, 内存消耗: 1616K, 提交时间: 2020-06-18 19:13:44

#include<bits/stdc++.h>
using namespace std;

int a[100005];
int main()
{
    int x,l,r,n,m;
    long long ans=0;
    scanf("%d%d",&n,&m);
    for(x=1;x<=n;x++)scanf("%d",&a[x]);
    for(x=0,l=r=1;r<=n;r++)
    {
    	x+=a[r];
    	while(x>=m)ans+=n-r+1,x-=a[l++];
	}
	printf("%lld\n",ans);
}

上一题