题目链接
After solving the Basic Gcd Problem, ZYB gives you a more difficult one:
Given an integer {n}n, find two subset A {A} A and B {B} B of { 1 , 2 , … , n } \{1,2,\dots,n\} {1,2,…,n} such that:
Please find two subsets with maximum value of m {m} m.
There are multiple test cases. The first line of input contains an integer T {T} T, indicating the number of test cases.
For each test case, there is only one line containing an integer n ( 4 ≤ n ≤ 2 × 1 0 5 ) {n} (4 \le n \le 2 \times 10^5) n(4≤n≤2×105)
It’s guaranteed that the sum of n {n} n of all test cases will not exceed 2 × 1 0 5 2 \times 10^5 2×105.
For each test case, output an integer {m}m in the first line. In the next {m}m lines, each contains two integers a i a_i ai and b i b_i bi ( gcd ( a i , b i ) > 1 (\gcd(a_i, b_i) > 1 (gcd(ai,bi)>1, denoting the i {i} i-th element in subset A {A} A and B {B} B.
If there are multiple solutions, you can output any of them.
2
4
10
1
2 4
4
3 9
5 10
8 2
4 6
这题典型的思维题,而且的 cf 原题,吐了
题目链接
我怕自己讲得不好,直接挂官方题解,间接明了:
AC代码如下:
#include
using namespace std;
typedef long long ll;
const int N=2e5+10;
int prime[N],k,t,n;
bool isprime[N],vis[N];
vector<pair<int,int> >ans;
vector<int>v[N];
void Prime(){
fill(isprime,isprime+N,1);
k=0;
prime[1]=0;
for(int i=2;i<N;i++){
if(isprime[i]){
prime[k++]=i;
for(ll j=2;i*j<N;j++)
isprime[i*j]=0;
}
}
}
void init(){
ans.clear();
for(int i=1;i<=n;i++) vis[i]=0,v[i].clear();
}
int main(){
Prime();
scanf("%d",&t);
while(t--){
scanf("%d",&n);
init();
int pos=upper_bound(prime,prime+k,n/2)-prime;
for(int i=pos-1;i>=1;i--){
int p=prime[i];
for(int j=p;j<=n;j+=p){
if(!vis[j]){
v[p].push_back(j);
vis[j]=1;
}
}
if(v[p].size()%2){
v[2].push_back(p*2);
v[p].erase(v[p].begin()+1);
}
int len=v[p].size()/2;
for(int i=0;i<len;i++){
ans.push_back({v[p][i],v[p][i+len]});
}
}
for(int i=2;i<=n;i++) if(!vis[i]&&i%2==0) v[2].push_back(i);
int len=v[2].size()/2;
for(int i=0;i<len;i++) ans.push_back({v[2][i],v[2][i+len]});
printf("%d\n",ans.size());
for(auto i:ans) printf("%d %d\n",i.first,i.second);
}
return 0;
}