Vijos 连续数之和 (组合数学)
Posted 心之所向 素履以往
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vijos 连续数之和 (组合数学)相关的知识,希望对你有一定的参考价值。
描述
有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的结果。
样例1
样例输入1
6 3
1
2
6
3
7
4
样例输出1
7
限制
各个测试点1s
来源
Matrix67 根据经典问题改编
1 /* 2 我们设sum为前缀和 3 首先要知道 4 (sum[j]-sum[i])%k==0 --> sum[j]%k==sum[i]%k 5 假设 sum[k]==sum[l] 那么 sum[k]-sum[l]==0 6 也就是 在[l+1,k]这段区间连续的和可以被k整除 7 那么假设 sum[i],sum[j],..sum[k](共bn个) 8 都是 MOD k 余数为k-1的sum 9 只需要从中任意取两个 就可以构成一个连续的区间的和可以整除k 10 11 注意余数为0 要单独加一次 12 */ 13 #include<cstdio> 14 #include<iostream> 15 #define MAXN 500010 16 #define MOD 1234567 17 18 using namespace std; 19 20 int n,k; 21 long long ans,a[MAXN]; 22 23 int b[100010]; 24 25 inline void read(int&x) { 26 x=0;int f=1;char c=getchar(); 27 while(c>‘9‘||c<‘0‘) {if(c==‘-‘) f=-1;c=getchar();} 28 while(c>=‘0‘&&c<=‘9‘) {x=(x<<1)+(x<<3)+c-48;c=getchar();} 29 x=x*f; 30 } 31 32 inline int c(int N,int M) { 33 return (N*(N-1)/2)%MOD; 34 } 35 36 int main() { 37 int temp=0; 38 read(n);read(k); 39 for(int i=1;i<=n;i++) { 40 read(temp); 41 a[i]=a[i-1]+temp; 42 ++b[a[i]%k]; 43 } 44 ans+=b[0]; 45 for(int i=0;i<k;i++) { 46 if(b[i]>=2) 47 ans=(ans+c(b[i],2))%MOD; 48 } 49 printf("%lld\n",ans); 50 return 0; 51 }
以上是关于Vijos 连续数之和 (组合数学)的主要内容,如果未能解决你的问题,请参考以下文章
vijos - P1302连续自然数和 (公式推导 + python)