题目传送门:Be Efficient
题意:输入n和m,然后输入有n个元素的一个序列,问有多少个子序列元素的和能整除m。
思路:求前缀和,利用一个前缀的一个定理求解。
前缀和的一个定理是:每次求的前缀和对m取余,两个相等的结果之间的序列的和就是m的倍数。
如上序号1、4的结果相同,则序号2、3、4的和是4的倍数,序号2、3的结果相同,则序号3是4的倍数。
注意:将储存取余结果的数组pre的pre[0]设置为1,因为后边前缀和取余为0,表明这一组自己就是4的倍数,直接从1开始。
PS:用long long,算错了数据范围,被爆int卡到吐……
代码:
/*
Time:2018/9/6
Writer:Sykai
Function:L
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <set>
#include <cstring>
#include <queue>
#define INF 0x3f3f3f3f
#define FRE() freopen("in.txt","r",stdin)
using namespace std;
const int maxn = 1e5+10;
const int MOD = 1e9 + 7;
typedef long long ll;
typedef pair<int,int> P;
ll pre[maxn],n,m;
inline void init()
{
memset(pre,0,sizeof(pre));
}
int main()
{
int T,cnt = 0;
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld",&n,&m);
init();
ll sum = 0,ans = 0;
pre[0] = 1;
for(int i = 1; i<=n; i++)
{
ll t;
scanf("%lld",&t);
sum = (sum+t) % m;
ans += pre[sum];
pre[sum]++;
}
printf("Case %d: %lld\n",++cnt,ans);
}
return 0;
}