B. Integral Array
B. Integral Array
题意:
对于一个序列a 如果对于任意ai aj [ai / aj] 也在序列中 就称为好数组
思路:
数据可达到1e6 显然暴力会超时
利用前缀和可以O(1) 地判断数字是否存在 序列中 记录每个数字的出现次数存到b数组中 然后再遍历1-c每次把b[i-1]加到b[i]中这样每个b[i]就是前缀和 即小于等于i的数的个数
因为给定了最高界限 c 所以只要在c范围内讨论问题即可
如果一个数x出现在数列中 而另一个数y没有出现在数列中 而它两的乘积x*y却出现在序列中 那么说明[x*y/x]不在序列中所以要输出no
因为是向下取整 所以要判断[x * y, x * (y + 1))之间的数
还有一些细节必须注意具体看代码注释
#include#define ll long long #define pi acos(-1) #define F ios::sync_with_stdio(false), cin.tie(0) using namespace std; const int mod = 1e9 + 7; const int N = 1e6 + 10; ll n, c, a[N], b[N], pre[N]; void solve(){ cin >> n >> c; for(int i = 1; i <= c; i++){ b[i] = 0; } int flag = 1; for(ll i = 1; i <= n; i++){ cin >> a[i]; b[a[i]] ++; } sort(a + 1, a + n + 1); //如果 序列中没有1就输出 no if(a[1] != 1) { cout << "No\n"; return; } //将b数组变成 前缀和 即b[i]表示小于等于i的数的个数 for(ll i = 1; i <= c; i++){ b[i] += b[i - 1]; } for(ll i = 1; i <= c; i++){ if(b[i] - b[i - 1]) continue;//i代表 序列中不存在的 //j代表序列中存在的 但是要注意不要用a[j] 来找存在的数会超时 //因为可能序列中每个数都一样且很小 而对于同一个数我们只要计算一次就好 //以下注释是错误示例 /* for(ll j = 1; j <= n; j ++) ... i * a[j] */ for(ll j = 1; j <= c; j++){ //大于c 直接退出 if(i * j > c) break; if(!(b[j] - b[j - 1])) continue; //右边界比c大时 应该取c if(b[min((i + 1) * j - 1, c)] - b[i * j - 1] > 0) { flag = 0; break; } } if(!flag) break; } if(!flag) cout << "No\n"; else cout << "Yes\n"; return; } int main() { F; int t; cin >> t; while(t--){ solve(); } return 0; }