CSUSTOJ-小樱的库洛牌(恶心的构造题)
Posted lonely-wind-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSUSTOJ-小樱的库洛牌(恶心的构造题)相关的知识,希望对你有一定的参考价值。
Description
众所周知,木之本樱有 (n) 张库洛牌,每张库洛牌按危险程度可以分成等级 (1-n) ,由于所有库洛牌都放在一起的太危险了,所以小樱想把 (n) 张库洛牌等分成 (k) 组,让每组危险程度的和的最大值和最小值的差值最小 ,但由于木之本樱只是友枝小学的学生,实在不知道该怎么分,于是她找到了聪明的 (ACMer) 。
input
第一行三个整数 (n, k) , ((1 leq n leq 1e5)) , ((1 leq k leq n)) ,并且保证 (n) 可以整除 (k)
output
输出 (k) 行,每行 (frac{n}{k}) 个整数 (可以输出任意一组解)
Sample Input 1
4 2
Sample Output 1
1 4
2 3
这是个恶心的找规律和构造题目。。。我们设(len=frac{n}{k}),即每组数的个数。很明显当(len\%2==0)的时候我们一定可以构造出(1-n,2-(n-1)...)这样两两相等的(frac{n}{2})个组合可以平均分配给每组。
接下来当(len)为奇数的时候才是重头戏,对于这种情况我们如果没有什么想法的话只能竟可能地去寻找规律。说实话我找了1个多小时才有意识地找到了QAQ。。。
我们可以发现的一个规律就是对于(len)为奇数而言,它分为2种情况,一个就是当(k)为偶数的时候,它的最小差值一定会是1,当(k)为奇数的时候他的最小差值是0。
那么我们现在就需要考虑怎么分配的问题了,很明显我们可以提出一个偶数的长度来减小工作量,那么我们肯定不能提出(len-1)这个偶数,因为这样的话就导致了最小差值为(k-1)了
那么我们可以考虑提出(len-3)这个偶数,那么前面的3个数就可以得到及时的调整,但我们目前所担心的就是前三个数的调整是否能够得到最优结果。事实上我们可以通过实验来验证的。我们将这个n个数分为((1,2,3...,k),(1,2,3...,k)...)这样的(n/k)组,然后我们就可以对于k组从这些组中每组挑选一个(这样的话由于每组有个基础值,所以我们可以都从1到k)这句话有点可能有点绕,但却是这题的最关键的地方。比如拿15 5举例,我们可以画出如下的匹配图形:
也就是得到了((1,3+5,5+10)(2,4+5,3+10)(3,5+5,1+10)(4,1+5,4+10)(5,2+5,2+10))这样的构造,我们可以算出他们每组的值都是一样的,所以可以得到最小差值为0。那么按照上面的规律,我们按顺序一个一个往下走就完事了,第一列是往下走的,第二列是从中间开始往下走然后如果超出边界了则直接到1继续往下走也就相当于首位相接了,对于第三列则是从n往上走的,走的步长为2,也是相当于首位相接了。
接下来当这个(k)为偶数的时候他就会发生变化,如下图:
第三列的2往上跳2步的时候到达了6这个位置,但6已经被占据了,只能退而求其次连上5这个数,那么这也就导致了这个差值为1的出现。接下来后面的所有数都会比正常的少1。
于是规律推完,此题结束!
以下是AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mac=1e5+10;
vector<int>g[mac];
int vis[mac];
int main(int argc, char const *argv[])
{
int n,k,len;
scanf ("%d%d",&n,&k);
if (k==1){
for (int i=1; i<=n; i++)
printf("%d%c",i,i==n?‘
‘:‘ ‘);
return 0;
}
len=n/k;
if (len%2==0){
int nb=1;
for (int i=1; i<=len/2; i++){
for (int j=1; j<=k; j++){
g[j].push_back(nb);
g[j].push_back(n-nb+1);
nb++;
}
}
for (int i=1; i<=k; i++){
for (auto x:g[i])
printf("%d ",x);
printf("
");
}
}
else {
int ns=k;
vis[ns]=1;
for (int i=1; i<=k; i++){
g[i].push_back(i);
if (len>1){
int su=(i+k/2)%(k+1);
if (i+k/2>k) su++;
g[i].push_back(su);
g[i].push_back(ns);
ns-=2;
if (ns<=0) ns+=k;
if (!vis[ns]) vis[ns]=1;
else vis[--ns]=1;
}
}
if (len>3){
for (int i=1; i<=k; i++){
for (int j=4; j<=(len-3)/2+3; j++){
g[i].push_back(i);
g[i].push_back(k-i+1);
}
}
}
for (int i=1; i<=k; i++){
int sum=0;
for (int j=0; j<len; j++){
printf("%d ",g[i][j]+sum);
sum+=k;
}
printf("
");
}
}
return 0;
}
以上是关于CSUSTOJ-小樱的库洛牌(恶心的构造题)的主要内容,如果未能解决你的问题,请参考以下文章
牛客练习——吐泡泡(简单的栈的运用题:别被多组输入恶心到了)
Twitter Follower数过80万 竹达彩奈发福利未公开魔卡少女樱COS一张
Android 逆向ART 脱壳 ( InMemoryDexClassLoader 脱壳 | BaseDexClassLoader 构造函数 | DexPathList 构造函数及后续调用 )(代码片