题目描述
旅行完了的牛牛又胖了,于是他终于下决心要戒掉零食,所以他带着他最爱的土豆回到了牛星,开始了在牛星种土豆和只吃土豆减肥的日子。(吃土豆能减肥么?)经过了辛勤的劳作,牛牛种的土豆奇迹般的收获了,于是他得到了很多很多很多很多的土豆(实在太多,数不过来了,你可以认为是无穷个)。他将这很多很多个土豆按照重量从小到大进行了排序,每个土豆的编号依次为1、2、3……N,然后他就惊奇地发现:由于牛星球的土壤很奇特,第i个土豆的重量正好是3^(i-1) 。
现在牛牛饿了要吃掉其中的若干个土豆。他每次拿的土豆的数目是任意的,选的土豆也是任意的。选中的土豆的总重量即每个土豆重量之和。例如:牛牛这一次拿了第一个土豆和第三个土豆,那么总重量为1+9=10。
牛牛想知道,在所有的选土豆方案里,他可以获得的第k大的“总重量”是多少。
输入描述:
有多组输入样例。
第一行是一个整数T,表示有T组测试样例,0 ≤ T ≤ 70。
之后的T行中,每一行有一个数字k。(k<=2^31-1)
输出描述:
针对每一个测试样例,输出一行;格式为:
“Case #A”,其中,A表示他可以获得的第k大的总重量。
题解
赤裸裸考思维,感觉这道题应该是本场比赛的签到题。
每一个数都对应一个排名,这个排名可以用二进制唯一表示,题目要你求在三进制体系下排名第K位的是谁,那么我们把给我们的排名看成一个01串,把这个01串对应到这个数字是否存在就好了。可以举几个样例自己算一算,好好理解一下
代码
#include<iostream> #include<algorithm> #include<map> #include<vector> #include<set> #include<string> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #include<stack> using namespace std; #define ll long long #define ull unsigned long long #define pb push_back #define pii pair<int,int> #define all(A) A.begin(), A.end() #define fi first #define se second #define MP make_pair #define rep(i,n) for(register int i=0;i<(n);++i) #define repi(i,a,b) for(register int i=int(a);i<=(b);++i) #define repr(i,b,a) for(register int i=int(b);i>=(a);--i) template<typename T> inline T read(){ T s=0,f=1; char ch = getchar(); while(!isdigit(ch)) {if(ch == '-') f=-1;ch = getchar();} while(isdigit(ch)) {s=(s<<3)+(s<<1)+ch-48;ch = getchar();} return s*f; } #define gn() read<int>() #define gl() read<ll>() template<typename T> inline void print(T x) { if(x<0) putchar('-'), x=-x; if(x>9) print(x/10); putchar(x%10+'0'); } //////////////////////////////////////////////////////////////////////// const int N=2e5+100; ll ans(ll num){ ll sum=0,t=1; while(num){ if(num&1)sum=sum+t; t*=3; num>>=1; } return sum; } //////////////////////////////////////////////////////////////////////// int main(){ int T=gn(); for(int z=1;z<=T;++z){ ll k=gl(); printf("Case #%d: %lld\n",z,ans(k)); } }