题解
- 题目大意:有n个球,m个格子,如果i格子放了x,那么i+1格子一定要放2*x,i-1格子一定要放x/2(整除),问第一个格子里最多有多少个球
- 可以发现第一个格子的数应该满足
- 那么我们就可以每次将n除去2^m-1然后统计奇数个数,然后在一直除2^m再统计奇数个数直到n为0
- 总共的奇数个数就是答案
代码
1 #include <cstdio>
2 #include <iostream>
3 #include <cstring>
4 #define ll long long
5 using namespace std;
6 const ll N=1e4+10,mo=1e11;
7 ll a[N],ans[N],b[N],n,t,k,len,x,y,z,m,T,num;
8 char s[N];
9 void chu(ll x)
10 {
11 ll r=0;
12 for (ll i=a[0];i>=1;i--) a[i]=r*mo+a[i],r=a[i]%x,a[i]/=x;
13 while (!a[a[0]]&&a[0]) a[0]--;
14 }
15 void count()
16 {
17 ll r=0;
18 for (ll i=a[0];i>=1;i--) ans[i]+=(r*mo+a[i])/2,r=a[i]%2;
19 r=max(ans[0],a[0]-1);
20 if (ans[r+1]) r++;
21 for (ll i=1;i<=r;i++) if (ans[i]>=mo) ans[i]-=mo,ans[i+1]++;
22 if (ans[r+1]) ans[0]=r+1; else if (ans[r]) ans[0]=r; else if (ans[r-1]) ans[0]=r-1;
23 }
24 int main()
25 {
26 scanf("%lld",&T);
27 while (T--)
28 {
29 memset(a,0,sizeof(a)),memset(ans,0,sizeof(ans));
30 scanf("%s%lld",s+1,&m),len=strlen(s+1),k=1,n=1;
31 for (ll i=len;i>=1;i--)
32 {
33 a[n]+=(s[i]-48)*k,k*=10;
34 if (k==mo) k=1,n++;
35 }
36 a[0]=n,chu(1<<(m-1)),n=a[1]%2,count(),ans[1]+=n;
37 while (a[0]) chu(1<<m),n=a[1]%2,count(),ans[1]+=n;
38 if (!ans[0]) ans[0]=1;
39 printf("%lld",ans[ans[0]]);
40 for (ll i=ans[0]-1;i>=1;i--)
41 {
42 ll k=mo/10;
43 while (ans[i]<k&&k>0) printf("0"),k/=10;
44 printf("%lld",ans[i]);
45 }
46 printf("
");
47 }
48 }