A
题目大意:
- 给定一个具有n (2 ≤ n ≤ 100) 个元素的数组
- 对这个数组每次可以使得 a[i] = a[i] - a[i - 1] (2 ≤ i ≤ n)
- 问对于这个给定的数组,是否可以通过操作使得a[i] = 0 (2 ≤ i ≤ n)
解法:
- 首先从下标为2的元素开始看,a[2]如果最后需要通过减去a[1]变成0,那么a[2] % a[1] == 0 && a[1] < a[2],是必须成立的。
- 然后下标为3的元素,因为a[1] < a[2] 所以把a[2]变成a[1],可以有更大的可能使得后面的数变成0,那么a[3] % a[1] == 0,也应该成立。
依次类推,条件就是 a[i] % a[1] == 0 (2 ≤ i ≤ n)
#include <iostream>
using namespace std;
const int N = 110;
int a[N];
int main()
{
int t;
cin >> t;
while(t --)
{
int n;
cin >> n;
for(int i = 1;i <= n;i ++) cin >> a[i];
int flag = 0;
for(int i = 2;i <= n;i ++) if(a[i] % a[1] != 0)
{
flag = 1;
break;
}
if(flag) puts("NO");
else puts("YES");
}
return 0;
}
B
题目大意:
- 给定三个数n, l , r (1 ≤ n ≤ 1e5, 1≤ l ≤ r ≤ 1e9).
- 构造一个具有n个元素的数组,使得 gcd(i, a[i]) 各不相同,其中a[i]属于[l, r]这个区间
解法:
- 当i = 1,a[i]的值无论为什么gcd(i, a[i]) == 1
- 当i = 2,首先gcd(i, a[i])不能为1,那么gcd(i, a[i]) 一定为2
- 当i = 3,gcd(i, a[i]) != 1 && gcd(i, a[i]) != 2,那么gcd(i, a[i]) 一定为3
以此类推,可以知道所有位置上的数,都是其下标的倍数。
那么问题就可以进行简化,现在问题就是判断对于每一个下标,它的某一个倍数是否在[l, r]区间内。
- 当i > r, 那么就不存在
- 当l <= i <= r,那么就直接选i
- 当i < l,首先判断 l 是否是 i 的倍数,如果不是就利用 l + i - l % i ,求得大于 l 的最小的 i 的倍数,然后判断这个数是否大于了r。
#include <iostream>
#include <map>
#include <vector>
using namespace std;
int main()
{
int t;
cin >> t;
while(t --)
{
int n, l, r;
cin >> n >> l >> r;
vector<int> res;
for(int i = 2;i <= n;i ++)
{
if(i > r) continue;
else if(l <= i) res.push_back(i);
else if(l % i == 0) res.push_back(l);
else if((l + (i - l % i)) <= r) res.push_back(l + (i - l % i));
}
if(res.size() < n - 1) puts("NO");
else
{
puts("YES");
cout << l << " ";
for(int i = 0;i < res.size();i ++) cout << res[i] << " ";
cout << endl;
}
}
return 0;
}