1. 程式人生 > >CF449C Jzzhu and Apples

CF449C Jzzhu and Apples

用兩個 def problem type 做的 clu ons size mat

傳送門

這道題好像一開始想到了差不多的做法orz?後來都不大敢相信就是這麽做的……有點瞎搞。

後來看了CF的官方題解,感覺還是挺有道理的。首先對於1和大於n/2的質數肯定是不行的,我們直接忽略。然後,對於每一個質數的倍數,我們肯定是把他們組合在一起更優。如果這些數有奇數個,那我們就把質數的2倍挑出來(因為2倍是最容易組合的!)

如果有偶數個就直接組合。

最後你肯定剩下的全都是偶數,那麽隨便組合就行啦!

直接用兩個棧模擬即可。

看一下代碼。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include
<iostream> #include<cmath> #include<set> #include<queue> #define pr pair<int,int> #define mp make_pair #define fi first #define sc second #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar(‘\n‘) using namespace
std; typedef long long ll; const int M = 200005; const int INF = 1000000009; int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < 0 || ch > 9) { if(ch == -) op = -1; ch = getchar(); } while(ch >= 0 && ch <= 9) { ans *= 10; ans += ch -
0; ch = getchar(); } return ans * op; } int n,p[M],stack[M],tot,cur,sta[M],cnt,now; bool np[M],vis[M]; pr ans[M]; void euler() { np[1] = 1; rep(i,2,n) { if(!np[i]) p[++tot] = i; for(int j = 1;i * p[j] <= n;j++) { np[i*p[j]] = 1; if(!(i%p[j])) break; } } } int main() { n = read(); euler(); rep(i,2,tot) { if(p[i] > n>>1) break; rep(j,1,n/p[i]) if(j != 2 && !vis[p[i] * j]) sta[++cur] = p[i] * j,vis[p[i] * j] = 1; if(cur&1) { sta[++cur] = p[i] << 1,vis[p[i] << 1] = 1; while(cur) ans[++cnt].fi = sta[cur--],ans[cnt].sc = sta[cur--]; } else { stack[++now] = p[i] << 1,vis[p[i] << 1] = 1; while(cur) ans[++cnt].fi = sta[cur--],ans[cnt].sc = sta[cur--]; } } rep(j,1,n>>1) if(!vis[j<<1]) stack[++now] = j << 1; if(now&1) now--; while(now) ans[++cnt].fi = stack[now--],ans[cnt].sc = stack[now--]; printf("%d\n",cnt); rep(i,1,cnt) printf("%d %d\n",ans[i].fi,ans[i].sc); return 0; }

CF449C Jzzhu and Apples