题解 P1254 【扇区填数】

xzyxzy

2018-07-16 21:12:28

Solution

有一个必须要知道的结论: $$ans=n*(n-1)+1$$ 虽然我不知道怎么证明(等我知道了我再来更新题解) Upd7.17:这个式子并不是正确的,比如n=7就不对,但是这是答案的极限,我们从大到小枚举答案然后想方设法构造方案,于是发现在这道题的测试点(n=2,3,4,5,6,8)上我们都可以在答案取到极限时成功构造出相应的方案 但是这个式子的含义是**每个数在一种方案中有且仅有一种表示方法** 计算有两种方式: 1.枚举一个分割线有n条,另一个分割线有n-1条,共n*(n-1)/2种方案,每种方案会产生两个数,然后加上全部算一起的一种方案 2.除开全部一起的方案,枚举扇区长度有n-1种,每种长度可以产生n个数,共n*(n-1)+1 所以知道了这个结论之后就很好做了,爆搜每一位是啥 注意这里n的范围是8(题面有误) ~~n=8我本机0.97s洛谷跑不过,所以打个表就好啦~~ 感谢star_city、zykykyk两位大爷的帮助! ```cpp #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> using namespace std; int n,A[20],s,ans,tot,B[20],tt; int v[23],tong[60],out[60][10]; inline void Check(int id) { if(n>4&&(!v[2]||(!v[3]&&!v[4])||(!v[5]&&!v[6]&&!v[7]&&!v[8]))) return; register int i,l,r,u; for(i=n+1;i<=n<<1;++i) A[i]=A[i-n]; for(i=1;i<=n<<1;++i) B[i]=B[i-1]+A[i]; for(l=1;l<=n;++l) for(r=l,u=l+n-1;r<=u;++r) tong[B[r]-B[l-1]]=id; for(i=1;i<=ans;++i) if(tong[i]!=id) return;tot++; for(i=1;i<=n;i++) out[tot][i]=A[i]; } void DFS(int x) { if(x>n) {if(s==ans) Check(++tt);return;} for(int i=1;i<=22;++i) if(!v[i]) { A[x]=i;v[i]=1;s+=i; if(s<=ans) DFS(x+1); v[i]=0;s-=i; } } void work1(); int main() { cin>>n;A[1]=1;s=1; printf("%d\n",ans=n*(n-1)+1); if(n==8)work1();DFS(2); for(int i=1;i<=tot;i++,puts("")) for(int j=1;j<=n;j++) printf("%d ",out[i][j]); } void work1() { printf("1 2 10 19 4 7 9 5\n1 3 5 11 2 12 17 6\n"); printf("1 3 8 2 16 7 15 5\n1 4 2 10 18 3 11 8\n"); printf("1 4 22 7 3 6 2 12\n1 5 9 7 4 19 10 2\n"); printf("1 5 15 7 16 2 8 3\n1 6 12 4 21 3 2 8\n"); printf("1 6 17 12 2 11 5 3\n1 8 2 3 21 4 12 6\n"); printf("1 8 11 3 18 10 2 4\n1 12 2 6 3 7 22 4\n"); exit(0); } ```