题解 P6195 【[EER1]迫害】
原题传送门。在我的博客中食用更佳。
【目录】
- 目录
- 写在前面
- 题意概括
- 思路
激动人心的代码实现环节- 尾声
【写在前面】
本题解的代码关系是递进的,每一次的Code无不是包含着作者的菜与艰辛。
如果有意见欢迎提出,但请私信(作者自愿禁言了),否则作者无法回复您。
【题意概括】
输入两个正整数
其中
现要求用这些卡片从
注意结果要对
【思路】
或许你从样例身上已经有了一些想法了:先将所有卡片
随后下一个数
那么,不妨令第一张卡片
随后,
同理:
我们就会发现,此时能表示到的最大的值就是
那么此时:
如果我们没有卡片
如果还有,那就可以令下一张卡片
发现当有两张卡片
咱们先停一停,找找规律:
当有
当有
由上可得,当有
如果你觉得两次得来的规律不可靠,也可以再看看有
那么,是时候进入下一章节了,我想你应该已经迫不及待了吧...
【激动人心的代码实现环节】
好了,咱先不管那么多,先按刚刚得到的还热乎着的规律打一发再说:
First Code:
#include<bits/stdc++.h>//万能头文件好
using namespace std;
#define ll long long//个人习惯
#define mo 1000000007
int main(){
ll n,m;
scanf("%lld%lld",&n,&m);//输入
printf("%lld\n",(n+1)* ( (ll) (pow(2,m)) ) %mo-1);//输出
//没错,就是这么简单!
return 0;//over!
}
看啊,那一个个绿色的AC是那么的可爱!
往下一翻:Emm怎么全错了。。
聪明的你一定发现了:我并没有给最后答案取余。那么简单再改一下:结果Q_Q。
不急,问题不大,至少没有TLE,况且比赛才开始呢。仔细想想...中间乘的时候是不是爆long long了?没错!就是这样!
那么我们就可以把算
Second Code:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mo 1000000007
int main(){
ll n,m,k=1,i;//注意k的初始值
scanf("%lld%lld",&n,&m);
for(i=1;i<=m;i++)k*=2,k%=mo;//用k来存储2^m的结果
printf("%lld\n",((n+1)*(k%mo)-1)%mo);
return 0;
}
很好,看来可以A掉了。成功解锁此题新死法:TLE。
看来,T3说的真好:
个人的遭遇,命运的多舛都使我被迫成熟,这一切的代价都当是日后活下去的力量。 —— 三毛
咱们打起精神再来。既然TLE是时间不够,那么就得让程序算
办法总比困难多。我们可以让循环变快一些。
若用一个变量
上Third Code:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mo 1000000007
int main(){
ll n,m,k=1,i,yu;//先全部定义好
scanf("%lld%lld",&n,&m);
yu=m%3;m/=3;//取余,自整除
for(i=1;i<=m;i++)k*=8,k%=mo;//算(2^3)^m
for(i=1;i<=yu;i++)k*=2,k%=mo;//算2^yu
printf("%lld\n",((n+1)*(k%mo)-1)%mo);
return 0;
}
再次喜提TLE。
嘿,别泄气啊,你看,TLE的点数不是少了几个?
程序能不能再快一点?
当然可以!为什么不让循环跨度再大一点呢?也就是使:
这次就不上Forth Code了,与Third Code是同理的。
结果:AC哈哈哈!
【尾声】
然而窝太篛了只A了
众所周知,月赛排名是先按分数,再按时间排序的。
百般无奈的我为了更上一层楼便开始琢磨...
能不能再快点?
当然可以!为什么不让循环跨度再大一点呢?(我绝对不会告诉你们这句话是从前面复制过来的)
于是,我让 毕竟不是正解),11ms(也不知它是怎么算的) 美滋滋~
还是上一下上述的Forth Code吧:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mo 1000000007
int main(){
ll n,m,k=1,i,yu;
scanf("%lld%lld",&n,&m);
yu=m%15;m/=15;
for(i=1;i<=m;i++)k*=32768,k%=mo;//如果我说32768是我口算的,你信吗?
for(i=1;i<=yu;i++)k*=2,k%=mo;
printf("%lld\n",((n+1)*(k%mo)-1)%mo);
return 0;
}
跑的挺快的记录。
顺便说一下,其实这道题作者有Sixteenth Code(好丢脸)。
码字不易啊(疯狂暗示 AWA