1. 程式人生 > >ZZULIOJ 2502: 建國與兩個陣列

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大佬提供)

分析:在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;
	}
}