题目链接:http://acm.csust.edu.cn/problem/4054
CSDN食用链接:https://blog.csdn.net/qq_43906000/article/details/109520681
Description
哈希是一只喜欢叼纸的小猫,他每次都可以叼一团纸回家,纸的体积为(1),同时,他还可以把家中所有的纸团(可以只有一个纸团)合并成一个纸团,这个纸团的体积为(所有纸团之和乘上p),但是,哈希家中容量有限,最多只能存在(k)个纸团
现在哈希想让家中所有纸团的体积之和为(n),请你告诉他是否有可能.
input
一行三个整数(n,p,k(1 leq n ,k,pleq 1e18))
output
如果可以,则输出"Just Do It",否则输出"No way".
Sample Input 1
10 4 3
Sample Output 1
Just Do It
Sample Input 2
11 4 3
Sample Output 2
No way
emmm,这题可能是我验题WA得最惨的一题了。。。思维要缜密
我们开始思考,第一回合拿(k_1)个纸团后乘上(p),第二个回合拿(k_2)个纸团后乘以(p)....
那么我们就可以得到一个表达式:((....(((k_1p+k_2)p+k_3)p+k_4)p.......+k_n)=n)
实际上化简出来就是(k_1p^n+k_2p^{n-1}+...+k_n=n)那么实际上就是用p进制来表示n,那么我们肯定要对(p=1)的情况处理掉,否则一旦n过于庞大就好T掉,那么我们就开始谨慎的讨论了:对于(p=1)的情况,如果k也为1,那么没什么好说的,n必须为1否则就直接GG,一旦k大于1,那么他就可以无限+1,一定会到达n。
接下来我们处理出p进制下的每一位的系数,我们知道第一次有k个位置给你放,也就是说如果(p^n)的系数大于k的话那就直接GG,融合之后一定会有一个纸团来占位,那么之后的所有的的系数都必须小于(等于k-1)
以下是AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mac=1e3+10;
ll a[mac];
ll qick(ll x,int b)
{
ll ans=1;
while (b){
if (b&1) ans*=x;
b>>=1;
x*=x;
}
return ans;
}
int main(int argc, char const *argv[])
{
ll n,p,k;
cin>>n>>p>>k;
if (p==1 && k!=1){
printf("Just Do It
");
return 0;
}
if (p==1 && k==1) {
if (n>1) printf("No way
");
else printf("Just Do It
");
return 0;
}
if (n<=k) {printf("Just Do It
"); return 0;}
ll nn=n,nb=0;
while (nn){
nn/=p;
nb++;
}
nb--;
for (int i=nb; i>=0; i--){
ll use=qick(p,i);
a[i]=n/use;
n-=a[i]*use;
}
int flag=0;
if (a[nb]>k) {printf("No way
"); return 0;}
for (int i=nb-1; i>=0; i--)
if (a[i]>k-1) {flag=1; break;}
if (flag) printf("No way
");
else printf("Just Do It
");
return 0;
}