$NOIP1997$ 题解报告
就只有一道题$QwQ$
$Luogu\ P1549$ 棋盘问题
就……暴搜可以过。线性筛预处理出质数,然后枚举每个位置填哪个数,判断一下是否合法。注意一下搜索策略,因为保证第一行和第一列的所有数之和最小,则使其他地方的数尽量大,即第一行和第一列从小到大枚举,其他位置从大到小枚举。
1 #include<bits/stdc++.h> 2 #define ri register int 3 #define ll long long 4 #define rl register ll 5 #define go(i,a,b) for(ri i=a;i<=b;i++) 6 #define back(i,a,b) for(ri i=a;i>=b;i--) 7 #define g() getchar() 8 #define il inline 9 #define pf printf 10 #define mem(a,b) memset(a,b,sizeof(a)) 11 using namespace std; 12 il int fr(){ 13 ri w=0,q=1;char ch=g(); 14 while(ch<'0'||ch>'9'){if(ch=='-')q=-1;ch=g();} 15 while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=g(); 16 return w*q; 17 } 18 const int N=102; 19 int n,m,v[N],prim[N],num,a[12][12]; 20 bool vis[N],ans=0; 21 il void ready(){ 22 go(i,2,m<<1){ 23 if(!v[i])v[i]=i,prim[++num]=i; 24 go(j,1,num){ 25 if(i*prim[j]>(m<<1)||prim[j]>v[i])break; 26 v[i*prim[j]]=prim[j]; 27 } 28 } 29 return; 30 } 31 il void work(ri x,ri y){ 32 if(x==1||y==1){ 33 go(i,2,m){ 34 if(ans)return; 35 if(vis[i])continue; 36 /*cout<<"x="<<x<<" y="<<y<<" "<<i<<endl; 37 if(x>1)cout<<"h="<<a[x-1][y]+i<<endl; 38 if(y>1)cout<<"l="<<a[x][y-1]+i<<endl;*/ 39 if(x>1&&v[a[x-1][y]+i]!=a[x-1][y]+i)continue; 40 if(y>1&&v[a[x][y-1]+i]!=a[x][y-1]+i)continue; 41 vis[i]=1,a[x][y]=i; 42 if(y==n)work(x+1,1); 43 else work(x,y+1); 44 vis[i]=0; 45 } 46 } 47 else{ 48 back(i,m,2){ 49 if(ans)return; 50 if(vis[i])continue; 51 /*cout<<"x="<<x<<" y="<<y<<" "<<i<<endl; 52 if(x>1)cout<<"h="<<a[x-1][y]+i<<endl; 53 if(y>1)cout<<"l="<<a[x][y-1]+i<<endl;*/ 54 if(v[a[x-1][y]+i]!=a[x-1][y]+i)continue; 55 if(v[a[x][y-1]+i]!=a[x][y-1]+i)continue; 56 vis[i]=1,a[x][y]=i; 57 if(x==n&&y==n){ans=1;return;} 58 if(y==n)work(x+1,1); 59 else work(x,y+1); 60 vis[i]=0; 61 } 62 } 63 return; 64 } 65 int main(){ 66 //freopen(".in","r",stdin); 67 //freopen(".out","w",stdout); 68 n=fr();m=n*n;ready(); 69 a[1][1]=1;work(1,2); 70 if(!ans)puts("NO"); 71 else{go(i,1,n){go(j,1,n)pf("%d ",a[i][j]);puts("");}} 72 return 0; 73 }