题目大意:给你一个序列1-n,你要找到尽可能多的匹配使得每个匹配值的gcd>1,输出匹配的个数和每个匹配
输入
2 4 10
输出
1 2 4 4 3 9 5 10 8 2 4 6
emmm,这题的话应该还是感觉比较好写的,先将素数筛出了,对每个素数p的点放入p,2p,3p,4p...kp(kp<=n),那么里面的数就可以任意匹配了,那么对于2这个素数我们先不急,我们先将3到n/2以内的素数的内容放好,对于每个素数的size,如果里面是偶数的话我们就任意匹配,如果是奇数的话,我们将2p保留下来,放入到2的内容中,剩余的任意匹配,最后我们再出来2这个值就好了。
以下是AC代码:
#include <bits/stdc++.h> using namespace std; #define debug printf("@#$#@%") const int mac=2e5+10; int vis[mac]; vector<int>prim[mac]; int vs[mac],val[mac]; int main(int argc, char const *argv[]) { int t,n; scanf ("%d",&t); for (int i=2; i<=sqrt(mac); i++) if (!vis[i]) for (int j=i*i; j<mac; j+=i) vis[j]=1; int cnt=0; for (int i=2; i<mac; i++) if (!vis[i]) val[++cnt]=i; while (t--){ int n; scanf ("%d",&n); for (int i=1; i<=n; i++) vs[i]=0; for (int i=1; 2*val[i]<=n; i++) prim[i].clear(),prim[i].push_back(val[i]); prim[1].push_back(4); vector<pair<int,int>>ans; for (int i=2; 2*val[i]<=n; i++){ for (int j=2*val[i]; j<=n; j+=val[i]){ if (vs[j]) continue; prim[i].push_back(j); vs[j]=1; } if ((prim[i].size()&1) && prim[i].size()>1){ ans.push_back(make_pair(prim[i][0],prim[i][2])); for (int j=3; j<prim[i].size(); j+=2){ ans.push_back(make_pair(prim[i][j],prim[i][j+1])); } prim[1].push_back(prim[i][1]); } else { for (int j=0; j<prim[i].size(); j+=2) ans.push_back(make_pair(prim[i][j],prim[i][j+1])); } prim[i].clear(); } for (int j=2*3; j<=n; j+=2){ if (vs[j]) continue; prim[1].push_back(j); } if ((prim[1].size()&1)) for (int i=1; i<prim[1].size(); i+=2) ans.push_back(make_pair(prim[1][i],prim[1][i+1])); else for (int i=0; i<prim[1].size(); i+=2) ans.push_back(make_pair(prim[1][i],prim[1][i+1])); printf ("%d ",ans.size()); for (int i=0; i<ans.size(); i++) printf("%d %d ",ans[i].first,ans[i].second); } return 0; }