Olya and magical square - 竞赛题解

借鉴了一下神犇tly的博客QwQ(还是打一下广告

终于弄懂了

Codeforces 传送门


『题目』(直接上翻译了)

给一个边长为 \(2^n(n>0)\) 的正方形,你需要对它进行恰好 \(k(k>0)\) 次“剪切”,“剪切”的方法是:选取一个边长不为 \(1\) 的正方形,将它剪成 \(4\) 个大小相同的正方形,不能挪动位置。

要求在 \(k\) 次操作后存在一条路径:从左下角的正方形到右上角的正方形,且路径上所有正方形的大小都相等。

求是否可行,若存在可行解,输出可行解的路径上的正方形的边长以 \(2\) 为底的对数


『解析』

其实比较容易看出来是一道结论(找规律)题,毕竟也就只有这种类型之类的题会把 \(k\) 设置为 \(10^{18}\) 这么大……

大概的解题思路是:对于每一种可能的路径上正方形的边长 \(2^i\),求出这种情况最少需要进行多少次剪切以及最多需要多少次,判断 \(k\) 是否在这个区间内。

不妨让路径先一直向上,然后一直向右。假设现在路径上正方形的边长是 \(2^i\),

  1. 先求一下最少次数

    这种情况的最少操作次数为 \(1+3+7+...+(2^i-1)\),感性理解一下——

    当 \(i=n-1\) 时显然最少需要进行 \(1\) 次操作,这样就会变成:



    如果进一步让 \(i=n-2\),那么我们就应该对上图的灰色块进行操作,也就是 \(3\) 次。……以此类推,就会得到上面的式子~
  2. 然后求最大次数

    显然(一般来说)在最少次数的基础下我们还可以再进行一些不会对答案造成影响的操作——也就是对除了左下角到左上角再到右上角的路径上的正方形(最左边、最上边的正方形),我们最多可以把它们全部剪成\(1*1\)的~

    令 \(f(siz)\) 为将边长为 \(2^{siz}\) 的正方形剪成 \(1*1\) 的操作次数,那么我们发现 \(2^{siz}\) 的边长剪 \(1\) 次会变成 \(4\) 个 \(2^{siz-1}\),再剪 \(4\) 次会变成 \(16\) 个 \(2^{siz-2}\)……

    以此类推,我们可以得到 \(f(siz)=1+4+4^2+...+4^{siz-1}\) 。

    假设现在正方形的边长为 \(2^a\),左上角的正方形为 \(2^b(b<a)\),如果按照最小方法剪,那么正方形可能长这样:



    上面的蓝色部分就是我们可以乱剪(不会对答案造成影响)的正方形,假设我们已经算出来了这一块蓝色部分全部剪成 \(1*1\) 的操作次数,然后如果按照最小方法继续剪,它就会变成这样:



    上面的橙色部分就是相较上一次剪切多出来的可以任意操作而不会影响答案的正方形(假设它们的大小不是 \(1*1\)),那么我们要算这一次可以任意剪切的次数就可以根据上一次(蓝色部分)加上这次(橙色部分)全部剪成 \(1*1\) 的操作次数~

    而我们发现橙色正方形的边长就是我们的路径上的正方形边长,所以可以直接套用 \(f()\) 函数计算。至于个数……假设上一次多出来的正方形(蓝色里面除去右下角的正方形)的个数为 \(tmp'\) ,那么这次多出来的正方形个数就是 \(tmp=(tmp-1)*4+5\),找规律嘛~

    那么最大操作数就是最少操作数加上将这些(橙色和蓝色)正方形剪成 \(1*1\) 的正方形的操作数。

那么我们只要枚举一下答案的路径上的正方形边长,判断 \(k\) 是否在最小操作数和最大操作数之间即可。但是我们可以看到 \(n\) 也不小……所以这里还有一个 特性

当 \(n \geq 32\) 时,答案就是 \(n-1\)

为什么?显然如果我们要将边长为 \(2^m(m \geq 31)\) 的正方形全剪成 \(1*1\) 的正方形的总操作次数已经超过了 \(10^{18}\) ,这就意味着我们可以将原来 \(n \geq 32\) 的正方形剪成 \(4\) 个边长为 \(2^{n-1}\) 的正方形,然后就尽可能地将右下角的那一个边长为 \(2^{n-1}\) 的正方形剪成 \(1*1\) 的,但是 \(k\) 并不够大,所以就可以将剩下的 \(k-1\) 次机会全部用完~

代码比较简单,但是论证思路还是非常严谨的!


『源代码』

/*Lucky_Glass*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll QPow(ll a,int r){ //快速幂
ll res=1ll;
while(r){
if(r&1) res*=a;
a*=a;
r>>=1;
}
return res;
}
ll Cut(int siz){ //把边长为 2^siz 的正方形剪成 1*1 的操作次数
return (QPow(4,siz)-1)/3;
}
int Solve(int n,ll k){
if(n>=32) return n-1;
else{
ll liml=0,limu=0,sam=1;
//liml:最少操作次数
//limu:在最少操作次数的基础上最多还能进行的操作次数使得答案不变化
//sam:按最少操作方法与路径上的正方形大小相同的正方形(除去路径上的)的最大个数,也就是进行最少操作后相较上一次多出来的可以任意操作的正方形的个数
for(int i=n-1;i>=0;i--){
liml+=(1<<n-i)-1;
limu+=sam*Cut(i);
sam=(sam-1)*2+5;
if(liml<=k && k<=limu+liml) //是否在范围内
return i;
if(k<liml) return -1;
}
}
return -1;
}
int main(){
int cas;scanf("%d",&cas);
while(cas--){
int n;ll k;
scanf("%d%lld",&n,&k);
int res=Solve(n,k);
if(res==-1) printf("NO\n");
else printf("YES %d\n",res);
}
return 0;
}

\(\mathfrak{THE\ END}\)

\(Thanks\ for\ reading!\)

没看懂的可以在 \(lucky\_glass@foxmail.com\) 随便问~

竞赛题解 - [CF 1080D]Olya and magical square的更多相关文章

  1. Codeforces Round #524 (Div. 2) D. Olya and magical square

    D. Olya and magical square 题目链接:https://codeforces.com/contest/1080/problem/D 题意: 给出一个边长为2n的正方形,每次可以 ...

  2. 竞赛题解 - CF Round #524 Div.2

    CF Round #524 Div.2 - 竞赛题解 不容易CF有一场下午的比赛,开心的和一个神犇一起报了名 被虐爆--前两题水过去,第三题卡了好久,第四题毫无头绪QwQ Codeforces 传送门 ...

  3. CF1080D Olya and magical square

    思路: 构造. 实现: #include <bits/stdc++.h> using namespace std; typedef long long ll; ll sum[]; int ...

  4. codeforces round#524 D - Olya and magical square /// 大概算是数学规律题?

    题目大意: t 个测试用例  (1≤t≤103) 给定n k  (1≤n≤10^9,1≤k≤10^18) 表示有一个边长为2^n的正方形格子 每次操作只能将一个格子切割为左上左下右上右下的四等分格子 ...

  5. 《ACM国际大学生程序设计竞赛题解Ⅰ》——基础编程题

    这个专栏开始介绍一些<ACM国际大学生程序设计竞赛题解>上的竞赛题目,读者可以配合zju/poj/uva的在线测评系统提交代码(今天zoj貌似崩了). 其实看书名也能看出来这本书的思路,就 ...

  6. 竞赛题解 - Karp-de-Chant Number(BZOJ-4922)

    Karp-de-Chant Number(BZOJ-4922) - 竞赛题解 进行了一次DP的练习,选几道题写一下博客~ 标签:BZOJ / 01背包 / 贪心 『题目』 >> There ...

  7. 竞赛题解 - Broken Tree(CF-758E)

    Broken Tree(CF-758E) - 竞赛题解 贪心复习~(好像暴露了什么算法--) 标签:贪心 / DFS / Codeforces 『题意』 给出一棵以1为根的树,每条边有两个值:p-强度 ...

  8. 竞赛题解 - Palisection(CF-17E)

    Palisection(CF-17E) - 竞赛题解 Manacher学到一定程度,也需要练一下有趣的题了-- (这是多老的题了 \(QwQ\))[传送门] 『题意』 给出一个字符串,求总共有多少对不 ...

  9. 竞赛题解 - NOIP2018 保卫王国

    \(\mathcal{NOIP2018}\) 保卫王国 - 竞赛题解 按某一个炒鸡dalao名曰 taotao 的话说: \(\ \ \ \ \ \ \ \ \ "一道sb倍增题" ...

随机推荐

  1. CSS清浮动方法总结

    浮动----会使当前标签产生上浮效果,从而导致父标签高度塌陷的问题 1. 给父元素指定高度 <div style="height:200px"> <div sty ...

  2. Python基础-接口与归一化设计、抽象类、继承顺序、子类调用父类,多态与多态性

    一.接口与归一化设计 Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能). 由 ...

  3. 关于Function原型对象和Object原型对象的一些疑惑

    网上有一道美团外卖的面试题是这样的: Function.prototype.a = 'a'; Object.prototype.b = 'b'; function Person(){}; var p ...

  4. MySQL数据库(3)----设置和使用自定义变量

    MySQL支持定义自己的变量.这些变量可以被设置为查询结果,这使我们可以方便地把一些值存储起来供今后查询使用. ; +-----------------+ | @HisName:= name | +- ...

  5. Apache服务器运维笔记(1)----运行多个Apache服务器

    所有的Apache管理员都会遇到一个问题,就是在一台物理系统上运行多个版本的Apache服务器,或是运行多个同一版本的Apache服务器的副本,对于前者,在编译时为不同版本的Apache指定不同的安装 ...

  6. CentOS 7运维管理笔记(1)----设置默认启动模式为GUI模式或命令行模式

    昨天在虚拟机中安装CentOS 7时选择了GNOME模式安装,开机默认进入GUI模式.网上搜找修改为默认命令行模式的方法,看到说修改 /etc/inittab文件,在最低下一行添加 但是 使用 cat ...

  7. 02_dubbo的SPI

    [dubbo为什么不采用JDK自带的SPI] 1.JDK自带的SPI(ServiceLoader)会一次性实例化扩展点所有实现,基本只能通过遍历全部获取,也就是接口的实现类全部加载并实例化一遍,如果我 ...

  8. c windows控制台输出颜色文字

    #include <windows.h> //设置文字颜色void SetColor(int ForgC){ WORD wColor; //We will need this handle ...

  9. winform 写入和读取TXT文件

    C# winform写入和读取TXT文件 string str; str=this.textBox1.Text; StreamWriter sw = new StreamWriter(Applicat ...

  10. Timeout occurred while waiting for latch: class 'COLUMNSTORE_ROWGROUP_COLLECTION'

    今天发现线上数据库主从延迟严重: SELECT ag.name AS ag_name, ar.replica_server_name AS ag_replica_server, dr_state.da ...