#Vijos P1090#连续数之和

14 篇文章 0 订阅
3 篇文章 0 订阅

组合数学二

时间限制: 1 Sec  内存限制: 64 MB

题目描述

有n个正整数排成一行。你的目的是要从中取出一个或连续的若干个数,使它们的和能够被k整除。 例如,有6个正整数,它们依次为1、2、6、3、7、4。若k=3,则你可以取出1、2、6,或者2、6、3、7,也可以仅仅取出一个6或者3使你所取的数之和能被3整除。当然,满足要求的取法不止以上这4种。事实上,一共有7种取法满足要求。 给定n和k,以及这n个数。你的任务就是确定,从这n个数中取出其中一个数或者若干连续的数使它们的和能被k整除有多少方法。 由于取法可能很多,因此你只需要输出它mod 1234567的值即可。

输入

第一行有两个正整数,分别代表n和k。输入数据保证有n小于等于500 000,k小于等于100 000。 以下n行每行一个正整数。这些正整数保证都不大于10 000。

输出

一个正整数。它应该是你的答案mod 1234567的结果。

样例输入

6 3
1
2
6
3
7
4

样例输出

7


求一段连续位置上数字和,对数列求前缀和sum,从第j + 1项到第i项的和:sum[ i ] - sum[ j ]

( sum[ i ] - sum[ j ] ) % k = 0

-> sum[ i ] ≡ sum[ j ] (mod k) i > j-> i >= j + 1(i = j + 1时是单独的一个数)

将sum分类,可以用k的剩余系来表示sum中的一类数,Z(k) = {0 , 1 , 2 , .... , k - 1}

对于每类数,由于i > j,有:(当余数为k1时,共有n个数余数为k1)

i = a1, j = a2,a3,a4,....,an(n - 1)组

i = a2 , j = a3, a4,....,an(n - 2)组

....

i = a(n-1) , j = an(1)组

所以对于余数k1,一共有(n - 1) + (n - 2) + ....+1 = (n - 1)*n / 2

当k1 = 0时, 不仅两个数一组, 它每个数本身也作为一种方案,共n种

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
typedef unsigned long long LL;
const int mod=1234567;
int R[100005];
int main(){
    int N,K,x;
    LL ans=0,sum=0;
    scanf("%d%d",&N,&K);
    for(int i=1; i<=N; ++i){
        scanf("%d",&x);
        sum+=x%K;
        ++R[sum%K];
    }
    ans=R[0]%mod;
    for(int i=0; i<K; ++i)
        ans=(ans+(R[i]*(R[i]-1)>>1))%mod;
    cout<<ans<<endl;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值