题目大意:给出数字,要求经过任意加减法(每个数只用一次),输出是否可整除被除数
解题策略:
(a)此题问你是否可以整除。我们知道整除的意思就是余数为0,所以判别是否可以整除,只要判余数是否为0,所以需要做取余数操作。(b)计算式(10+11)% 3 = (10%3 + 11%3)% 3,其中%表示取余数操作。你可以验算一下,看看这个算式是否成立。(c)r是余数,队列里存放的都是余数。(d)在c语言中,(-1)% 3 = -1。这样(1 - 2)% 3 = (-1)% 3 = -1,即余数是负数。为了避免负数,我们可以这样计算(1 - 2 + 3)% 3 = 2 % 3 = 2,这条语句r = (cur - temp+ divisor) % divisor;就是这个意思。事实上,你课堂上看到,如果不加 divisor,提交到UVa上去后,得到的结果Run Time Error。这是因为当r为负数时,visited[r]的下标就越界了。
/*
UVA 10036 Divisibility
AC by J.Dark
ON 2013/3/27
Time 0.216s
*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
const int maxn = 10005;
using namespace std;
int Num, divisor, num[maxn];
bool divisible;
vector <bool> visit;
/
void initial(){
divisible = false;
divisor = 0;
//qq.clear();
}
void input(){
cin >> Num >> divisor; //大数据输入须用scanf,否则会时间很慢
for(int i=0; i<Num; i++) cin >> num[i];
}
void solve(){
int cur, r, temp, qqsize;
queue <int> qq;
qq.push(0);
//大BFS,一直没掌握,今天好好练练~
for(int i=0; i<Num; i++){
qqsize = qq.size();
visit.clear();
visit.resize(divisor);
while(qqsize--)
{
cur = qq.front();
qq.pop();
temp = abs(num[i]) % divisor;
r = (cur + temp) % divisor;
if(!visit[r]){ //当前切点是否访问过
visit[r] = true;
qq.push(r);
}
temp = abs(num[i]) % divisor;
r = (cur - temp + divisor) % divisor; //仔细思考会~
if(!visit[r]){ //当前切点是否访问过
visit[r] = true;
qq.push(r);
}
}
}
while(!qq.empty()) //若队列不为空
{
if(qq.front() == 0){
divisible = true;
break;
}
else{ qq.pop();}
}
if(divisible)
cout << "Divisible" << endl;
else
cout << "Not divisible" << endl;
}
/
int main(){
int testCase;
while(cin >> testCase)
{
while(testCase--)
{
initial();
input();
solve();
}
}
//system("pause");
return 0;
}