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. 系统变量 %USERPROFILE%

    可以用CMD的SET命令来查看现有的系统变量,“="前的部分用%括起来就是.   常用: %USERPROFILE% =C:\Users\用户名 %SystemRoot% =C:\WINDO ...

  2. Qt 资料大全

    https://blog.csdn.net/liang19890820/article/details/51752029 简述 发福利了.发福利了.发福利了,重要的事情说三遍... 为了方便更多Qte ...

  3. 多线程 读写锁SRWLock

    在<秒杀多线程第十一篇读者写者问题>文章中我们使用事件和一个记录读者个数的变量来解决读者写者问题.问题虽然得到了解决,但代码有点复杂.本篇将介绍一种新方法——读写锁SRWLock来解决这一 ...

  4. mysql 修改数据库密码

    MYSQL5.7以下版本的数据库密码使用的是 mysql这个数据库里的user表的password这个字段, 修改密码只需: 1.update MySQL.user set password=pass ...

  5. Windows ->> FIX: “The security database on the server does not have a computer account for this workstation trust relationship”

    前几天在做AlwaysOn实验时遇到搭建活动目录域时某台已经加入AD的机器无法以域管理员账户登录的情况. 报错信息是:The security database on the server does ...

  6. Linux文件系统检查错误

    我们的Linux系统在无法启动时候,通常需要进入单用户模式下进行修改一些配置文件,或调整一些参数方可.但是在进入单用户模式后,我们的/文件系统是只读模式,无法进行修改,那么这个时候我们就需要用到一条命 ...

  7. 第六周 day6 python学习笔记

    1.Python面向对象编程OOP(Object Oriented Programming) 封装:可以隐藏实现细节,使代码模块化 继承:可以扩展已存在的代码模块,可以使代码实现重用 多态:一种接口, ...

  8. KDD 2013推荐系统论文

     LCARS: A Location-Content-Aware Recommender SystemAuthors: Hongzhi Yin, Peking University; Yizhou S ...

  9. 在WAS下找不到主机名称的问题

    发生错误: 联合 ADMU0036E: Deployment Manager 不能根据名称主机 cdzfwas2 在地址 127.0.0.1 查找           期间发生错误:正在回滚到原始配置 ...

  10. 第三方库RATreeView的使用记录

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u012951123/article/details/36421939 由于项目须要用到树状列表,能够 ...