P9577「Cfz Round 1」Dead Cells
思路
Step1.暴力
考虑到数据范围很小,所以可以暴力模拟操作,赛时直接去想更优的情况,倒是没去想模拟,所以这里就不展开了。
Step2.有点思维难度的做法
首先发现在过程中,只有乘以 \(2\) 和除以 \(2\) 的操作,所以向上取整的情况只会出现在细胞数量为 \(1\) 的情况。
首先讨论 \(a\) 和 \(b\) 的大小情况。
-
若 \(a>b\),则除以 \(2\) 的次数一定比乘以 \(2\) 的次数多,所以如果没有特殊情况的话,答案一定是 \(1\)。既然我这么说了,这道题就肯定有特殊情况,那么特殊情况是什么呢?如果乘以 \(2\) 的最后一次操作出现在除以 \(2\) 的最后一次操作之后的话,答案会是 \(2\)。那么会有更多的乘以 \(2\) 的操作出现在最后一次除以 \(2\) 的操作之后吗?肯定是没有的,因为 \(a>b\) 所以在两次除法操作中最多有一次乘法操作。
-
若 \(a<b\),那么每次除以 \(2\) 前,一定乘以了若干次 \(2\),所以最终答案就是 \(2^{\lfloor \frac k a \rfloor - \lfloor \frac k b \rfloor}\)。
对于第二种情况,考虑使用快速幂,时间复杂度应该是 \(O(\log ({\lfloor \frac k a \rfloor - \lfloor \frac k b \rfloor}))\)。(蒟蒻不会算时间复杂度,如果错了可以私信或者评论告诉我)
AC 12ms code
#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
long long a,b,k,ans=1;
long long qsm(long long a,long long b)
{
if(b<=0) return 1;
long long res=1;
while(b)
{
if(b&1) res=res*a%mod;
a=a*a%mod,b>>=1;
}
return res;
}
int main()
{
scanf("%lld%lld%lld",&a,&b,&k);
if(a>b&&k/a*a>k/b*b) printf("2"),exit(0);//特殊情况
printf("%lld",qsm(2,k/a-k/b));
return 0;
}