齿轮(精打细算的二分)
头一次看到二分还要精打细算的……
首先是公式推导:
所以,本质来说,用一个循环遍历 r 作为 r1,然后找一个数 ri = r*q 即可,二分嘛。
但是注意,如果缺了:
if (a[i] * q > a.back()) break;
就不行了,不能AC,就算你改成:
if (a[i] * q > a.back()) continue;
也不行,不然怎么说是精打细算的二分呢,一点亏都吃不得。
还有一点就是需要特别判断 n==1 && q==1 的情况,因为我们推导的公式中是 n!=1 的情况下才满足的。
AC:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
// 首先推出公式 wi=w1*(r1/ri)
// 即 qi=r1/ri,所以 qi*r1=ri
// 所以,本质来说,用一个循环遍历r作为r1,然后找一个数 R=r*qi即可,二分嘛
int n, m;
int main()
{
cin >> n >> m;
vector<int>a(n);
for (int i = 0; i < n; i++)
cin >> a[i];
sort(a.begin(), a.end());
while (m--)
{
int q, f = 0;
cin >> q;
if (q == 1 && a.size() == 1) //特殊情况,首个齿轮作为最后的齿轮
{
cout << "YES" << endl;
continue;
}
//一般情况,首个齿轮不作为最后齿轮
for (int i = 0; i < n; i++)
{//如果相乘后已经超过a的范围了,当前和之后一定不行,因为a是递增的嘛,现在都不行了,之后更大,更不行
if (a[i] * q > a.back())
break;
int index = lower_bound(a.begin(), a.end(), a[i] * q) - a.begin();
if (a[index] == a[i] * q && index!=i) //还需要排除:不能找首个齿轮作为最后的齿轮的情况
{
cout << "YES" << endl;
f = 1;
break;
}
}
if(!f) cout << "NO" << endl; //将所有的r1都列举了,还是没有
}
return 0;
}