ZZULIOJ 2502: 建国与两个数组

题目描述

    建勋这几天在学习关于数组的知识,他遇到了一个难题,用他学过的数组知识好像解决不了。建勋只好去求助聪明的建国,题目是这样的:有两个数组,第一个包含了1到n共n个数字,第二个包含了1到m共m个数字。建勋想要从两个数组中各挑选出一个整数x,y,使得x,y的和为k的倍数。
建国想利用这个机会考考你们,请问有多少种组合的方式?

输入

第一行输入一个整数T,表示样例数量。(1 <= T <= 1000)
接下来T行,每行输入三个整数n,m,k。(1 <= n, m, k <= 1000)

输出

对于每个样例,输出满足的对数。

样例输入 Copy

2
1 1 1
6 7 7

样例输出 Copy

1
6

提示

第一个样例只有(1,1)1种。
第二个样例有(1,6),(2,5),(3,4),(4,3),(5,2),(6,1)共6种。

方法一(感谢PK/ZHY大佬提供)

扫描二维码关注公众号,回复: 4869332 查看本文章

分析:在n+m的有效区域内暴力枚举一层数组n以内的数字i,当(m+i)能被k整除时,即为可贡献的对数

#include<iostream>
using namespace std;
int main()
{
	int t,n,m,k,sum;cin>>t;
	while(t--)
	{
		sum=0;
		cin>>n>>m>>k;
		for(int i=1;i<=n;i++)
		{
			sum+=((i+m)/k-i/k);//暴力枚举单层数组n,搜寻其中可贡献的对数
		}
		cout<<sum<<endl;
	}
}

方法二(由笔者本人提供)

分析:先从n,m中找最大数和最小数,在n+m的范围内,我们可以循环枚举k的倍数i,当i小于等于最小数min时,此时组合数量由i来决定,有且只有i-1种组合情况,即 (1,i-1),(2,i-2)。。。。(i-1,1)。当i小于等于最大数max+1时,max能承受i的所有组合情况,此时组合数量由min来决定,有且只有min种组合情况,即(1,i-1),(2,i-2)。。。。(min,i-min)。当i大于最大数max+1时,此时max就不能承受所有组合情况了,就要减掉一部分。减去数量为(i-max-1);不过组合数量仍然是由min来决定的,只不过要减去额外的数量,有min-(i-max-1)种组合情况。即(i-max,max),(i-max+1,max-1),(min,i-min)

第三种情况可能稍微有些复杂,多理解就能明白了。

#include<iostream>
using namespace std;
int main()
{
	int x,n,m,k,sum;
	cin>>x;
	while(x--)
	{
		cin>>n>>m>>k;
		sum=0;
		int min=n<m?n:m;
		int max=n>m?n:m;
		for(int i=k;i<=n+m;i=i+k)
		{
			if(i<=min)//当i小于等于最小数min时,此时组合数量由i来决定,有且只有i-1种组合情况
			sum+=(i-1);
			else if(i<=max+1)//当i小于等于最大数max+1时,max能承受i的所有组合情况,此时组合数量
			sum+=min;        //由min来决定,有且只有min种组合情况
			else if(i>max+1)//当i大于最大数max+1时,有min-(i-max-1)种组合情况
			sum+=(min-(i-max-1));
		} 
		cout<<sum<<endl;
	}
}

猜你喜欢

转载自blog.csdn.net/basketball616/article/details/85839569