P4752题解
分析+解法
这题显然不能硬乘出来,于是考虑一种记录因数再比较的做法,但是注意这里可以只用记录是质数的因子,为什么?因为题目已经给出
线性筛质数:运用链表,每一次枚举链表中的
for ( int i = 0; i < 1000005; i++ ) prime[i].bef = i - 1 , prime[i].aft = i + 1;
for ( int i = 2; prime[i].bef <= 1000000; i = prime[i].aft )
{
cnt = 0;
for ( int h = 2; i * h <= 1000000; h = prime[h].aft ) q[++cnt] = i * h;
for ( int h = 1; h <= cnt; h++ ) aa = prime[q[h]].bef , bb = prime[q[h]].aft , prime[aa].aft = bb , prime[bb].bef = aa;
}
for ( int i = 2; i <= 1000000; i = prime[i].aft ) p[++cmp] = i;
二分查找:因为质数数组是严格递增的,于是可以运用二分查找的性质,以
int fnd( ll x[] , ll y )
{
if ( x[upper_bound( x , x + 202515 , y ) - x - 1] == y ) return 1;
return 0;
}
下面我们就进入最后一个板块:判断是否只多出来一个质数。如何做?我们本应该很简单的运用桶排,但是无奈数据规模过于庞大,我们运用优先队列,找到质数都push到队列里去,最后扫一遍两个队列,如果出现了不一样的,也就是 NO 。如果到最后有且仅有一次遇到不同的,就可以,否则就不可以。
下面是代码实现:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll p[202515] , cmp , q[1000005] , cnt , aa , bb , t;
int fnd( ll x[] , ll y )
{
if ( x[upper_bound( x , x + 202515 , y ) - x - 1] == y ) return 1;
return 0;
}
priority_queue<int> p1 , p2;
struct P
{
int bef , aft;
bool flag = true;
}prime[1000005];
ll m , n , a[100005] , b[100005];
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL) , cout.tie(NULL);
for ( int i = 0; i < 1000005; i++ ) prime[i].bef = i - 1 , prime[i].aft = i + 1;
for ( int i = 2; prime[i].bef <= 1000000; i = prime[i].aft )
{
cnt = 0;
for ( int h = 2; i * h <= 1000000; h = prime[h].aft ) q[++cnt] = i * h;
for ( int h = 1; h <= cnt; h++ ) aa = prime[q[h]].bef , bb = prime[q[h]].aft , prime[aa].aft = bb , prime[bb].bef = aa;
}
for ( int i = 2; i <= 1000000; i = prime[i].aft ) p[++cmp] = i;
cin >> t;
while ( t-- )
{
cin >> n >> m;
for ( int i = 1; i <= n; i++ )
{
cin >> a[i];
if ( fnd( p , a[i] ) ) p1.push( a[i] );
}
for ( int i = 1; i <= m; i++ )
{
cin >> b[i];
if ( fnd( p , b[i] ) ) p2.push( b[i] );
}
bool flag = false , jug = true;
if ( p1.size() <= p2.size() ) cout << "NO\n";
else
{
while ( !p2.empty() )
{
if ( p1.top() != p2.top() && !flag ) flag = true , p1.pop();
else if ( p1.top() != p2.top() && flag )
{
cout << "NO\n" , flag = false , jug = false;
break;
}
else p1.pop() , p2.pop();
}
if ( flag || p1.size() == 1 && p2.size() == 0 ) cout << "YES\n";
else if ( jug ) cout << "NO\n";
}
while ( !p1.empty() ) p1.pop();
while ( !p2.empty() ) p2.pop();
}
return 0;
}