給出一正整數
,找到
的兩個子集合
,使:
(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