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. Python 2 和Python 3的区别

    print input urlopen print print在版本2的使用方法是: print 'this is version 2' 也可以是 print('this is version 2') ...

  2. 分分钟搞懂 HD 钱包

    转自:http://blog.sina.com.cn/s/blog_12ce70a430102v8c7.html 第一次看到 HD 这个词被用在比特币钱包中时,很容易就把它理解成硬件(Hardware ...

  3. webstorm出现黑色块光标

    取消掉此项对勾即可

  4. jq扩展

    方法一(不常用)$.myjq = function(){alert("hello myjQuery);}方法二声明:$.fn.myjq=function(){$(this).text(&qu ...

  5. SQL Server ->> Memory Allocation Mechanism and Performance Analysis(内存分配机制与性能分析)之 -- Minimum server memory与Maximum server memory

    Minimum server memory与Maximum server memory是SQL Server下配置实例级别最大和最小可用内存(注意不等于物理内存)的服务器配置选项.它们是管理SQL S ...

  6. .net 面向对象程序设计深入](1)UML

    1.UML简介 Unified Modeling Language (UML)又称统一建模语言或标准建模语言. 简单说就是以图形方式表现模型,根据不同模型进行分类,在UML 2.0中有13种图,以下是 ...

  7. Deep Learning Drizzle

    Deep Learning Drizzle Drench yourself in Deep Learning, Reinforcement Learning, Machine Learning, Co ...

  8. linux:相关命令以及笔记

    首先,在linux 或者 unix里没有任何的反馈就叫成功,例如: (1)命令执行成功的样子:返回了登录用户信息 (2)命令执行失败的样子:没有返回任何东西 1.按键出现状况 解决:可以使用ctrl+ ...

  9. ZT sem_init sem_wait sem_post sem_destroy

    sem_init() 2009-06-26 16:43:11|  分类: linux |字号 订阅       信号量的数据类型为结构sem_t,它本质上是一个长整型的数.函数sem_init()用来 ...

  10. ZT 设计模式六大原则(4):接口隔离原则

    设计模式六大原则(4):接口隔离原则 分类: 设计模式 2012-02-27 08:32 17948人阅读 评论(21) 收藏 举报 设计模式classinterfacecstring框架 定义:客户 ...