题目描述
建勋这几天在学习关于数组的知识,他遇到了一个难题,用他学过的数组知识好像解决不了。建勋只好去求助聪明的建国,题目是这样的:有两个数组,第一个包含了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大佬提供)
分析:在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;
}
}