1. 程式人生 > >【XSY1522】燈 亂搞

【XSY1522】燈 亂搞

urn oid freopen i++ AI string stdout pre 除了

題目大意

?  \(n\)盞燈排成一列,標號\(1\)\(n\),一開始標號為\(1\)的燈亮著。

?  現在依次對於\(2\)~\(n\)的每一個質數\(p_i\),指定一盞亮著的燈\(a_i\),點亮所有標號為\(a_i\pm kp_i\)的燈。

  輸出任意一種方案即可

?  \(n\leq100000\)

題解

?  我們可以把燈的編號減\(1\),變成\(0\)~\(n-1\)

?  先用線性篩把質數篩出來

?  如果對於每一個質數都指定編號\(0\)的燈,就可以把除了\(1\)之外的所有燈點亮。

?  所以我們的目標是點亮\(1\)號燈

?  我們要找兩個質數\(p_1,p_2\),滿足\(p_1|p_2-1,p_1^2\geq n,p_2^2\geq n,p_1+p_2\leq n-1\)

,然後就可以給\(p_1\)指定\(p_1+1\),給\(p_2\)指定\(p_1+p_2\)。因為所有偶數都在\(p=2\)時被點亮了,所以這樣就可以把全部燈點亮了。

?  但是我們會發現n比較小時這個方法有時候會找不到答案,我們只需要寫一個暴搜把\(n\leq50\)的情況全部搜出來。

?  我也不知道第\(55\)行的那個剪枝是不是對的反正能搜出一組解。

代碼

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility> using namespace std; typedef long long ll; typedef pair<int,int> pii; int p[1000010]; int b[1000010]; int cnt; int a1[1000010]; int a2[1000010]; int a[1000010]; int cnt1,cnt2; int ans[1000010]; int c[1000010]; int d[1000010]; int n; int tcnt; void dfs(int x) { if(x>cnt) { int i; for
(i=1;i<=n;i++) if(!a[i]) return; // printf("printf(\"%d %d\\n",tcnt,n); // for(i=1;i<=tcnt;i++) // printf("%d\\n",ans[i]); // printf("\");"); printf("%d %d\n",tcnt,n); for(i=1;i<=tcnt;i++) printf("%d\n",ans[i]); exit(0); } int i,j; for(i=1;i<=n;i++) if(a[i]) { int s=0; for(j=i;j<=n;j+=p[x]) { s+=!a[j]; a[j]++; } for(j=i-p[x];j>=1;j-=p[x]) { s+=!a[j]; a[j]++; } ans[x]=i; if(s) dfs(x+1); for(j=i;j<=n;j+=p[x]) a[j]--; for(j=i-p[x];j>=1;j-=p[x]) a[j]--; } } int main() { // freopen("light.in","r",stdin); // freopen("light.out","w",stdout); scanf("%d",&n); memset(b,0,sizeof b); int i,j; cnt=0; for(i=2;i<=n;i++) { if(!b[i]) p[++cnt]=i; for(j=1;j<=cnt&&i*p[j]<=n;j++) { b[i*p[j]]=1; if(i%p[j]==0) break; } } tcnt=cnt; if(n<=50) { memset(a,0,sizeof a); a[1]=1; if(p[cnt]==n) { ans[cnt]=1; cnt--; } dfs(1); printf("%d %d\n",tcnt,n-1); for(i=1;i<=tcnt;i++) printf("1\n"); return 0; } printf("%d ",tcnt); if(p[cnt]==n) { ans[cnt]=1; cnt--; } n--; memset(a,0,sizeof a); int cnt3=0; for(i=1;i<=cnt;i++) { if(ll(p[i])*p[i]<=n) a1[++cnt1]=p[i]; else { a2[++cnt2]=p[i]; d[++cnt3]=p[i]; } ans[i]=1; } for(i=1;i<=cnt1;i++) { ans[i]=1; for(j=a1[i];j<=n;j+=a1[i]) a[j]++; } for(i=1;i<=cnt2;i++) c[a2[i]-1]=i; int x=0; for(i=cnt2;i>=1;i--) { for(j=a2[i];j<=n;j+=a2[i]) if(c[j]&&a2[i]+j<=n-2) { x=i; ans[i+cnt1]=a2[i]+2; ans[c[j]+cnt1]=a2[i]+j+2; break; } if(x) break; } printf("%d\n",n+1); for(i=1;i<=tcnt;i++) printf("%d\n",ans[i]); return 0; }

【XSY1522】燈 亂搞