ZZULIOJ 2502: 建国与两个数组 (思维题 详细题解)

ZZULIOJ 2502: 建国与两个数组 (思维题 详细题解)

这个题目是一道非常有意思的题目, 有很多种解法, 在这儿我只讨论一种最容易直观理解的解法
考虑一下, 因为求两数和为k的倍数, 我们就可以把每个数都先%k, 分为了k类, 用a,b保存起来, a[i]即为n中%k后为i的数量, b[i]同理
这样我们不难发现, 凑k的倍数就简化成了凑k, 那固然只能取i和k-i, 例如k= 7, a[2]=2, 那么只能取b[5], 一共则有a[2]*b[5]种凑法
所以答案即为sum(a[i]*b[k-i]), 注意对a[0]和b[0]的特殊处理

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef  long long LL;
const LL maxn = 1010;

int main()
{
    int n, m, k, T;
    int a[maxn], b[maxn];
    cin >> T;
    while(T--){
        cin >> n >> m >> k;
        //通过%7把a,b分为余数为0..k, k类
        ms(a, 0); ms(b, 0);
        for(int i = 1; i <= n; i++)
            a[i%k]++;
        for(int i = 1; i <= m; i++)
            b[i%k]++;

        LL sum = LL(a[0]*b[0]); //一定要加强转
        for(int i = 1; i <= k; i++)
            sum += a[i]*b[k-i]; //直接相乘

        cout << sum << endl;
    }

	return 0;
}