基础算法–数组配对
Description
数组配对任务描述:给你一个长度为n的数组A和一个正整数k,问从数组中任选两个数使其和是k的倍数,有多少种选法对于数组a1=1,a2=2,a3=2而言:(a1,a2)和(a2,a1)被认为是同一种选法
Input
输入n,k,n<=1000000,k<=1000,第二行有n个整数,大小不超过1e9
Output
输出符合题意的选法个数
很容易想到两个for循环,然后i和j相加取余,但是这样时间复杂度太大
根据((i%k)+(j%k))%k=0这个公式,我们可以想到,先把数组中的数组进行取余然后计算相同余数的个数,存放在另一个数组中。
for(int i=0;i<n;i++)
{
int t;
scanf("%d",&t);
a[t%k]++;
}
在主函数中,我们可以只用1层for循环,我们可以使用i来表示j这里的i和j都是代表的存放余数数组的下标,j=(k-i)%k,这里的i是之前的一个数%k后的值,我们要求另一个数,根据((i%k)+(j%k))%k=0这个公式,另一个数必须要和i相加等于0。
我们可以换个方式理解j=(k-i)%k,i和j都是一个数同k取余后的结果,我们要这两个相加后再取余k还等于0,那么我们已知了i,所以j就可以求出来了,至于为什么后面还要跟一个%k,是因为有余数等于0的情况,而k-0=k不符合题意
注意最后结果还要用long long
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <string>
#include <stack>
#include <queue>
#include <map>
using namespace std;
const int inf=0x3f3f3f3f;
const int MAX=1e6+5;
int a[MAX];
/*
数组配对
从数组中任意选择两个数,求其是k的倍数的配对有多少组
*/
int main()
{
int n,k;
while(~(scanf("%d%d",&n,&k)))
{
long long sum=0;
memset(a,0,sizeof(a));
for(int i=0;i<n;i++)
{
int t;
scanf("%d",&t);
a[t%k]++;
}
int j=0;
for(int i=0;i<k;i++)
{
j=(k-i)%k;
if(j<i) continue;
if(j==i)
sum+=(long long)a[i]*a[i]-1/2;
else
sum+=(long long)a[i]*a[j];
}
printf("%lld\n",sum);
}
return 0;
}