正题
题目大意
mmm个盒子,
当第iii个盒子中放了xxx,那么i+1i+1i+1个盒子中就必须放2x2x2x(i<=mi<=mi<=m)。
求1∼n1\sim n1∼n,mmm个盒子,求第一个盒子中可以放多少个
解题思路
1号盒子中的肯定越小越好。
要求满足条件那么首先x∗2m−1≤nx*2^{m-1}\leq nx∗2m−1≤n
那么x≤n/2m−1x\leq n/2^{m-1}x≤n/2m−1。
然后奇数是肯定可以放进去的,
然后对于每个
xxx,会封锁x∗2i(i<m)x*2^i(i<m)x∗2i(i<m)。
之和我们会发现x∗2mx*2^mx∗2m又可以放进去了。
以此类推
我们可以发现x∗2km(x%2==1,k≥0)x*2^{km}(x\%2==1,k\geq0)x∗2km(x%2==1,k≥0)
所以我们考虑枚举kkk。
开始先计算最大的xxx,统计一次奇数个数。
其实枚举kkk,就是每次让nnn除与2m2^m2m,然后统计一遍奇数个数。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll mod=1e11;
const ll W=1000;
ll a[W+10],ans[W+10],m,t,l,al;
char s[W*10+10];
void print(ll x){if (x>9) print(x/10); putchar(x%10+48); return;
}
void init()
{memset(s,0,sizeof(s));scanf("%s",s+1);scanf("%lld",&m);l=strlen(s+1);ll t=0,k=1;for(ll i=l;i>=1;i--){a[t]+=(s[i]-48)*k;k*=10;if(k==mod) t++,k=1;}l=W;al=0;
}
void div(ll x)
{ll g=0;for(ll i=l;i>=0;i--){a[i]+=g*mod;g=a[i]%x;a[i]/=x;}while(!a[l]&&l>=0) l--;
}
void count_odd(){ll g=0,i;ans[0]+=a[0]%2;for(i=l;i>=0;i--){ans[i]+=(a[i]+g*mod)/2;g=a[i]%2;}ll t=max(l-1,al);if(ans[t+1]) t++;for(i=0;i<=t;i++)if(ans[i]>=mod){ans[i+1]++;ans[i]-=mod;}if(ans[i]>0) al=i;else al=i-1;
}
void write()
{print(ans[al]);while(al--){if(ans[al]<1e10) putchar(48);if(ans[al]<1e9) putchar(48);if(ans[al]<1e8) putchar(48);if(ans[al]<1e7) putchar(48);if(ans[al]<1e6) putchar(48);if(ans[al]<1e5) putchar(48);if(ans[al]<1e4) putchar(48);if(ans[al]<1e3) putchar(48);if(ans[al]<1e2) putchar(48);print(ans[al]);}putchar('\n');
}
int main()
{scanf("%lld",&t);while(t--){memset(a,0,sizeof(a));memset(ans,0,sizeof(ans));init();div(1<<(m-1));count_odd();while(a[0]){div(1<<m);count_odd();}write();}
}