题目大意:给定一个数和一个序列 计算这个序列中有多少个子序列的和是这个数的倍数。
思路:a[i]+a[i+1]+..+a[j] = s[j]-s[i],如果要和是其倍数, 则表示s[j]-s[i]能够整除那个数,只要s[j]和s[i]对那个数的余数相同就可以了啊,所以,将各个和按余数分堆!! 每个堆选择两个出来,即(n*n-1)/2;
ps: 余数分堆很常用!! 序列为两个相减也很常用!!
代码如下:
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int i,cas,chushu,a,m,sum[50005];
int yushu[1000001];
cin>>cas;
while(cas--)
{
cin>>chushu>>m;
sum[0]=0;
for(i=0;i<m;i++) //计算各个和的余数
{
cin >>a;
sum[i+1] = (sum[i]+a)%chushu; //取余是关键
}
for(i=0;i<chushu;i++) //各个余数的个数初始化
yushu[i]=0;
for(i=0;i<=m;i++) // 计算各个余数的值 即 按余数分堆
yushu[sum[i]]++;
long long count = 0;
for(i=0;i<chushu;i++)
{
if(yushu[i]>=2) //相同的余数选择
count += (long long)yushu[i]*(yushu[i]-1)/2;
}
cout<<count<<endl;
}
return 0;
}
最后(50000*50000-1)/2 超int了 折腾了好久才改成long long 在我机器上都跑不起来 就A了 - -!