前缀和--Be Efficient(Light Oj 1134)

题目传送门: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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值