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. 原生ajax与封装的ajax使用方法

    当我们不会写后端接口来测试ajax时,我们可以使用node环境创建一个本地服务器. 1.创建一个本地服务器可参考http://www.cnblogs.com/heyujun-/p/6793900.ht ...

  2. 关于echart 图表自适应问题的解决办法

    <div id="divEnergy" style="width: 100%; height: 300px; border: 5px solid red; &quo ...

  3. Windows API 编程----将错误代码转换成错误描述信息

    Windows编程有时会因为调用函数而产生错误,调用GetLastError()函数可以得到错误代码.如果错误代码为0,说明没有错误:如果错误代码不为0,则说明存在错误. 而错误代码不方便编程人员或用 ...

  4. chengfa

    public class ddddd{ public static void main(String[] args) { ; ; i <= m; i++) { ; j <= i; j++) ...

  5. idea maven 依赖问题

    今天发现,原来idea引用maven依赖的时候,优先依赖的是本地.但是有个问题,如果我删除了一个packet,如果刚刚好本地另外一个项目里面也有这个对于的packet,idea的智能提示 是 将其导入 ...

  6. Spring3实战第二章第二小节 IOC依赖注入 list和map集合

    Spring有多种依赖注入的形式,本篇文章仅介绍Spring通过xml进行IOC配置的方式. 1.Set注入 2.构造器注入 平常的Java开发中,程序员在某个类中需要依赖其它类的方法. 通常是new ...

  7. Android学习——Service(一)

    这篇博文来介绍Android另一个十分重要的组件,Service.Service和Activity很类似,区别在于它运行在后台,不可见且没有界面.Service的优先级高于Activity,当系统负载 ...

  8. java面试题之----jdbc中使用的设计模式(桥接模式)

    1.JDBC(JavaDatabase Connectivity) JDBC是以统一方式访问数据库的API. 它提供了独立于平台的数据库访问,也就是说,有了JDBC API,我们就不必为访问Oracl ...

  9. centOS 7 简单设置(虚拟机)

    1.修改主机名 hostnamectl set-hostname 2.ssh连接慢的问题解决 vim /etc/ssh/sshd_config UseDNS=no GSSAPIAuthenticati ...

  10. ldconfig: /usr/lib/libpython2.6.so.1.0-gdb.py is not an ELF file - it has the wrong magic bytes at the start.

    https://bugzilla.redhat.com/show_bug.cgi?id=562980