Light Oj - 1134 Be Efficient(前缀和)
题目传送门: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卡到吐……
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 Time:2018/9/6 3 Writer:Sykai 4 Function:L 5 */ 6 #include <iostream> 7 #include <cstdio> 8 #include <algorithm> 9 #include <set> 10 #include <cstring> 11 #include <queue> 12 #define INF 0x3f3f3f3f 13 #define FRE() freopen("in.txt","r",stdin) 14 using namespace std; 15 const int maxn = 1e5+10; 16 const int MOD = 1e9 + 7; 17 typedef long long ll; 18 typedef pair<int,int> P; 19 ll pre[maxn],n,m; 20 21 inline void init() 22 { 23 memset(pre,0,sizeof(pre)); 24 } 25 26 int main() 27 { 28 int T,cnt = 0; 29 scanf("%d",&T); 30 while(T--) 31 { 32 scanf("%lld%lld",&n,&m); 33 init(); 34 ll sum = 0,ans = 0; 35 pre[0] = 1; 36 for(int i = 1; i<=n; i++) 37 { 38 ll t; 39 scanf("%lld",&t); 40 sum = (sum+t) % m; 41 ans += pre[sum]; 42 pre[sum]++; 43 } 44 printf("Case %d: %lld\n",++cnt,ans); 45 } 46 return 0; 47 }