D 然然的烦恼(武汉工程大学第四届ACM新生赛)
链接:https://ac.nowcoder.com/acm/problem/229579?&headNav=acm.
题目描述
为庆祝嘉心糖破k百万人大关,然然决定今天去吃夹心糖。二次元糖果店展示出了一列按顺序摆放的n颗夹心糖,每颗夹心糖有一个固定的甜度 ai (1 ≤ i ≤ n)。然然想一口吃连续的一列夹心糖,为表示她很开心,她想吃的这一列连续的夹心糖甜度和一定要是 k 的整数倍。摆在她面前的夹心糖实在是太多了,她想知道她一共有多少种连续夹心糖可以吃。
输入描述:
第一行包含两个整数n(1≤n≤100000)和k(1≤k≤100000)。
第二行k个整数 ai(1 ≤ a ≤ 100000)。
输出描述
一个整数,代表然然的选择数量。
示例1
输入
5 2
1 2 3 4 5
输出
6
说明
第一种:2
第二种:4
第三种:1 2 3
第四种:3 4 5
第五种:1 2 3 4
第六种:2 3 4 5
思考:
化简问题为:求出连续子序列的和%k=0的个数;
首先我们将一个思想:
a%c=x;b%c=x
那么:(a-b)%c=0;
所以我们只要知道前面有多少个余数相同的,那答案就加这么多。
我们现在我们看样例:
5 2
1 2 3 4 5
先求出前 i 项和
sum[ ]={1,3,6,10,15}
sum里面对2取余分别为:
{1,1,0,0,1}
第一个数前面没有对2取余为1的数,所以ans+0;
第二个数前面有1个对2取余为1的数,所以ans+1;
第三个数前面没有对2取余为0的数,但是本身就对2取余为0,所以ans+1;
第四个数前面有1个对2取余为0的数,且本身本身对2取余0,所以ans+2;
(sum[4]为1个,sum[4]-sum[3]为1个,所以+2)
代码:
#include<iostream>
#define ll long long
const int N=1e5+10;
using namespace std;
ll sum[N];
ll t[N];
int main()
{
ll n,k;
cin >> n >> k;
ll ans=0;
for(int i=1;i<=n;++i)
{
cin >> sum[i];
sum[i]+=sum[i-1];
}
t[0]=1;
for(int i=1;i<=n;++i)
{
ans+=t[sum[i]%k];
t[sum[i]%k]++;
}
cout << ans << endl;
return 0;
}