解题思路:
1. 两重嵌套:
按序取出一个数,查找其后面能否相加被k整除
2.数学组合法:
把数挨个对k进行取余后看做小球,放入a[0]~a[k-1]的小桶里,如果t%k==0,那么a[0]小桶里的数任意组合即可,然后查找像a[1]与a[k-1]这类相加等于K的小桶,对里面的球进行组
法一:
此算法较简单,但时间复杂度高
#include <stdio.h>
int main()
{
int n, k;
scanf("%d%d", &n, &k); // 读入序列长度 n 和取余数 k
int a[n]; // 定义一个数组 a,存储原始序列
int cnt = 0; // 记录能够被 k 整除的数对数量
int i, j; // 循环变量
for(i = 0; i < n; i++) // 读入整个序列
{
scanf("%d", &a[i]);
}
for(i = 0; i < n; i++) // 枚举第一个数
{
for(j = i + 1; j < n; j++) // 枚举第二个数
{
if((a[i] + a[j]) % k == 0) // 如果两数之和能被 k 整除,就计数
{
cnt++;
}
}
}
printf("%d\n", cnt); // 输出所求答案
return 0; // 程序结束
}
小编在这里提供第二种思路:(好的想法评论区见呐)
(想来想去,觉得小桶的说法会形象一点)
#include <stdio.h>
#define ll long long // 定义 long long 类型
int n, k;
int a[100000]; // 全局变量
void wyf1()
{
memset(a, 0, sizeof(a)); // 清空数组 a
scanf("%d%d", &n, &k);
int i, t;
for(i = 0; i < n; i++)
{
scanf("%d", &t);
a[t % k]++; // 按照余数分类记数
}
}
void wyf2()
{
ll ans = 0; // 记录可组合的数的个数
int i, j;
for(i = 0; i < k; i++)
{
j = (k - i) % k; // i与j相加等于k
if(j < i) // j < i,说明已经计算过
break;
else if(j == i) // j == i 时,计算可组合的数目
ans += 1ll * a[i] * (a[i] - 1) / 2; // a[0]小桶里球的组合;
else // 下标相加为k的情况
ans += 1ll * a[i] * a[j];
}
printf("%lld\n", ans); // 注意输出的数据类型是 long long
}
int main()
{
wyf1(); // 读入数据
wyf2(); // 计算并输出结果
return 0;
}
如果你不看完小编辛苦码的字,小编会很生气的