给出一正整数
,找到
的两个子集合
,使:
(1)
(2)令
,存在两种排列方式
,
使得对于
。html
2
4
10ios
1
2 4
4
3 9
5 10
8 2
4 6c++
实际上是个CF原题 Codeforces450E
整体思路是先找到全部小于
的质因子
,而后构造"
"之类的倍数形式。
对于某一个质因子
,咱们最多能够找到
个它的倍数(其实还要在这个基础上去减掉已经被计算过的数字,记为
)。
若是个数
为偶数,那就直接两两配对完事。
若是是奇数,在配对完以后咱们剩下一个数,为了保证能配对的尽可能多,咱们能够去找一个偶数,
把它放在另外一个容器里,在其余全部质因子完成配对后,对这个容器里的那些偶数随意地两两排列便可(gcd起码也有2)。web
质数筛的代码出现了一些问题,还须要调整…数组
#include <bits/stdc++.h> using namespace std; const long long MAXN=2e5; int prime[MAXN];//素数数组 bool is_prime[MAXN+10];//is_pri[i]表示i是素数 bool vis[MAXN+10];//是否被访问 int rest[MAXN+10];//当出现奇数个的时候被拎出来的偶数 int pow_prime[MAXN+10];//n范围内p的倍数、且未被访问过 int answer[MAXN+10][3];//存答案 //返回n之内素数的个数 long long sieve(long long n) { for(int i=0; i<=n; i++) { is_prime[i]=true; vis[i]=false; } is_prime[0]=is_prime[1]=false;//首先标记0和1不是素数 is_prime[2]=true;//标记2是素数 for(int i=2; i<=sqrt(n); i++) { if (is_prime[i]) //若是i是素数 { for(int j=i*i; j<=n; j+=i)//全部i的倍数都不是素数 is_prime[j]=false; } } long long p=0; for(int i=2; i<=MAXN; i++) { if (is_prime[i]) { prime[++p]=i; } } return p; } void solve1() { long long sum_prime=sieve(MAXN);//质数个数 int t; scanf("%d", &t); while(t--) { memset(vis, false, sizeof(vis));//每次重置vis的访问状况 long long n, m=0; scanf("%lld", &n); long long maxP=1; long long sum_rest=0;//匹配剩下的个数的总数 for(int i=sum_prime; i>=1; i--)//找出最大的质数 { if (prime[i]*2<=n) { maxP=i; break; } } for(int i=maxP; i>=1; i--) { long long p=prime[i];//质因子 long long sum_vis=0;//计算未被访问的p的倍数的个数 for(int j=p; j<=n; j+=p) { if (!vis[j]) { pow_prime[++sum_vis]=j;//存储p的倍数、且未被使用的 } } if (sum_vis==1)//一个的时候没法配对 continue; if (sum_vis%2==1)//奇数 { int pos=1; for(int j=1; j<=sum_vis; j++) { if (pow_prime[j]%2==0)//找到第一个是偶数的(貌似能够直接2*p?) { pos=j; break; } } rest[++sum_rest]=pow_prime[pos];//加入rest vis[pow_prime[pos]]=true;//更新访问标记 for(int j=1; j+1<=sum_vis; j+=2)//开始配对 { m++; if (j==pos) j++; answer[m][1]=pow_prime[j]; if (j+1==pos) j++; answer[m][2]=pow_prime[j+1]; vis[pow_prime[j]]=true;//更新访问标记 vis[pow_prime[j+1]]=true;//更新访问标记 } } else//偶数任意配对 { for(int j=1; j+1<=sum_vis; j+=2)//开始配对 { m++; answer[m][1]=pow_prime[j]; answer[m][2]=pow_prime[j+1]; vis[pow_prime[j]]=true;//更新访问标记 vis[pow_prime[j+1]]=true;//更新访问标记 } } } if (sum_rest>=2)//rest内的配对 { for(int i=1; i+1<=sum_rest; i+=2) { m++; answer[m][1]=rest[i]; answer[m][2]=rest[i+1]; } } printf("%lld\n", m); for(int i=1; i<=m; i++) { printf("%lld %lld\n", answer[i][1], answer[i][2]); } } } int main() { // ios_base::sync_with_stdio(false); // cin.tie(0); // cout.tie(0); #ifdef ACM_LOCAL freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); long long test_index_for_debug=1; char acm_local_for_debug; while(cin>>acm_local_for_debug) { cin.putback(acm_local_for_debug); if (test_index_for_debug>100) { throw runtime_error("Check the stdin!!!"); } auto start_clock_for_debug=clock(); solve1(); auto end_clock_for_debug=clock(); cout<<"\nTest "<<test_index_for_debug<<" successful"<<endl; cerr<<"Test "<<test_index_for_debug++<<" Run Time: " <<double(end_clock_for_debug-start_clock_for_debug)/CLOCKS_PER_SEC<<"s"<<endl; cout<<"--------------------------------------------------"<<endl; } #else solve1(); #endif return 0; }
赛后发现质数筛和一些细节错误致使经过率0.00%
这破题真就百度之星呗
DrGilbert 2020.7.20app