computermaths 2020-05-15
我好菜啊。。。数学不会数据结构不会博弈不会图论也不会,现在构造也不会了。。。
今天看似来了俩构造。然而一个是凭空想象的结论题(好难证。。。)还有一个是提答
于是我就凭空想象了,然而我菜所以猜错了,然后炸了,倒是也比多数人多了$10pts$
于是我就去提答了,然而这道题如果想认真写的话分数都不低,然后拿了个大概大众分就结束了
然后最后还有点时间写$T2$暴力的$20pts$来着 ,这时候突然钻出来了一个牛爷爷(窗口抖动)问我提答怎么交
我懵了(为啥不直接问教练),然后反正我最后暴力没交上去,我就无了
(牛爷爷天天$rk1$啊,这不是我说的)
(话说以前提答题都是怎么交上去的。。?)
T1:心的旋律(circle)
大意:构造一个两侧都有$n$个点的二分图,要求$k = \sum\limits_{A \subseteq [1,n]} [ |f(A)|<|A| ] $。$f(A)$指$A$集合点的所有出边到达的点的并集。$n \le 32,k \le 2^n$
首先$<$的限制比较麻烦,我们把条件改成大于等于(同时把$k$也改成$2^n-k$)。把$\sum$那个式子叫做一个图的 对应值 。
首先如果$k=0$,由于空集的存在,无解。
然后我们只要猜到:可以构造一种图满足左侧点连的右侧点集合为包含关系,且如果存在大小为$x$的集合就存在大小为$x-1$的集合。
为了方便我们强制集合就是一个$[1,size_i]$的前缀。同时把所有左侧点按照$size$排序。
然后这个图就相当于一个单调不减的$size$序列且满足$0 \le size_{i-1} \le size_i \le 1$。
我们设所有$size_i - size_{i-1} =1$的位置$i$我们把它丢进一个$B$集合里。设$m=|B|$
那么这个图的对应值就是:
$\sum\limits_{i=1}^{m} \binom{n}{i} - \sum\limits_{i=1}^{m} \binom{B_i-1}{i}$
需证:
1)对于任意$m$,大小为$m+1$的$B$集合对应的值比大小为$m$的大(设这个问题为$proof(n,m)$)
也就是说,大小为$m+1$的$B$集合对应的最小值 比 大小为$m$的$B$集合的对应最大值 要大。
我们作差一下,减号前面的部分抵消只剩下一项$\binom{n}{m+1}$
大小为$m+1$的集合要尽量小,也就是后面减去的集合要尽量大,那么就满足$B_i=n+i-(m+1)$
然后后面的那堆组合数就是$\sum\limits_{i=1}^{m+1} \binom{n+i-m-2}{i}$
这是一条斜线上的组合数求和,也就相当于是一列,直接组合恒等式干掉,得到这玩意就是$\binom{n}{m+1}-1$
所以$minval(m+1)-maxval(m)=1$
2)对于$m$相同时,$B$对应二进制下较大的,对应值较小
也就是说,两个$B$对位比较,第一次错开的位置,两数中较大者,对应值更小。
于是我们就直接从这个第一次错开的位置开始考虑,假如更高位上已经有$x$个$1$然后当前位是$M$。
我们发现我们需要证明的就是$proof(M-1,m-x-1)$。所以也已经证出来了。
3)每种$B$集合都与一个$0< \le 2^n$对应值一一对应。
上面的证明中,我们已经知道了在刚才的比较关系中,$min-max=1$也就是元素是两两相邻,$B$为空时显然是$1$。故得证。
综上,$B$集合写成二进制数后,第一关键字为1$的个数$第二关键字为权值排序后,排名为$i$的数对应值就是$i$(排名从$1$开始)
然后就逐位确定地构造一下就行了。枚举$1$的个数再枚举每一位填啥。
T2:幻化成风(count)
不会。有空回来补$60pts$暴力。营养丰富。
T3:大家佛(cut)
大意:提答。给定$n \times m$权值随机的矩阵,要求你把它分成$k$个联通块,使得块和最大值-块和最小值尽量小。
给出$84pts$的生成代码。
#include<bits/stdc++.h> using namespace std; char input[10],output[10]; int n,m,w,k,mtx[1005][1005];long long tot; int pre[1000],ans[1005][1005]; int main(){ for(int test=1;test<=10;++test){ sprintf(input,"cut%d.in",test);freopen(input,"r",stdin); sprintf(output,"cut%d.out",test);freopen(output,"w",stdout); scanf("%d%d%d%d",&n,&m,&k,&w);tot=0; for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)scanf("%d",&mtx[i][j]),tot+=mtx[i][j]; if(test==1){ puts("1 1 1 1 1 1 1 1 1 1"); puts("1 1 1 1 1 1 1 1 1 1"); puts("2 2 2 2 2 2 2 1 1 2"); puts("2 2 2 2 2 2 2 2 2 2"); puts("3 3 3 3 3 2 2 2 2 2"); puts("3 3 3 3 3 3 3 3 3 3"); puts("4 4 4 4 4 4 3 3 3 3"); puts("4 4 4 4 4 4 4 4 4 4"); puts("4 5 4 5 5 5 5 5 5 5"); puts("5 5 5 5 5 5 5 5 5 5"); } if(test==2){ puts("1 1 1 1 3"); puts("1 2 2 1 3"); puts("1 2 2 1 3"); puts("1 2 2 2 3"); puts("3 3 3 3 3"); } if(test==3){ puts("1 1 1 1 1"); puts("2 2 2 1 1"); puts("2 2 2 2 1"); puts("3 2 3 3 3"); puts("3 3 3 3 3"); } if(test==4){ int p=1,tot=0,co=1; while(p<=m){ if(tot+mtx[1][p]+mtx[2][p]+mtx[3][p]<=60)ans[1][p]=ans[2][p]=ans[3][p]=co,tot+=mtx[1][p]+mtx[2][p]+mtx[3][p]; else if(tot+mtx[1][p]+mtx[2][p]<=60)ans[1][p]=ans[2][p]=co,ans[3][p]=++co,tot=mtx[3][p]; else if(tot+mtx[1][p]+mtx[3][p]<=60)ans[1][p]=ans[3][p]=co,ans[2][p]=++co,tot=mtx[2][p]; else if(tot+mtx[2][p]+mtx[3][p]<=60)ans[2][p]=ans[3][p]=co,ans[1][p]=++co,tot=mtx[1][p]; else if(tot+mtx[1][p]<=60)ans[1][p]=co,ans[2][p]=ans[3][p]=++co,tot=mtx[2][p]+mtx[3][p]; else if(tot+mtx[2][p]<=60)ans[2][p]=co,ans[1][p]=ans[3][p]=++co,tot=mtx[1][p]+mtx[3][p]; else ans[1][p]=ans[2][p]=ans[3][p]=++co,tot=mtx[1][p]+mtx[2][p]+mtx[3][p]; p++; } for(int i=1;i<=n;++i,puts(""))for(int j=1;j<=m;++j)printf("%d ",ans[i][j]),ans[i][j]=0; } if(test==5){ for(int x=1;x<=k;++x){ int tg=tot/k+(x<=tot%k); for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(!ans[i][j]&&tg>=mtx[i][j])ans[i][j]=x,tg-=mtx[i][j]; } for(int i=1;i<=n;++i,puts(""))for(int j=1;j<=m;++j)printf("%d ",ans[i][j]); } if(test>=6&&test!=9){ for(int i=1;i<=k;++i)pre[i]=pre[i-1]+n*m/k+(i<=n*m%k); pre[k+1]=pre[k]+1; int tot=0,x=1,y=1,p=1; while(x<=n){ tot++; if(tot>pre[p])p++; ans[x][y]=p; if(x&1){if(y==m)x++;else y++;} else{if(y==1)x++;else y--;} } for(int i=1;i<=n;++i,puts(""))for(int j=1;j<=m;++j)printf("%d ",ans[i][j]),ans[i][j]=0; } if(test==9){ for(int i=1;i<=n;++i,puts(""))for(int j=1;j<=m;++j)printf("%d ",(j-1)/(n/k)+1); } } }
对于较大的数据,可以蛇行走位遍历整个矩阵然后按照权值砍蛇。可以优化到$92pts$
Set,List,Map的区别和功能到底是怎样的?其实它是与数组区分开来的。与数学中的集合最接近,两者都不包含重复元素。它的有些实现类能对集合中的键对象进行排序。切记在用到MAP时一定需要传入两个参数