洛谷2320 bzoj1192 鬼谷子的钱袋
题意概述:把正整数n分为m个正整数,m个正整数中不允许出现复数个非1的正整数,保证所有小于n的正整数都可以用一部分正整数的和表示,并且使m尽量小。
这道题不知道为啥bzoj上没有要求输出方案,导致我把bzoj的程序粘到洛谷上瞬间全wa。
思想还是非常简单的,第一个钱袋装n/2个金币,第二个装n/2/2个金币,第三个……
这样可以用和的形式表示任意小于n的正整数。
显然这样是最优解,而且基于不断除2得出的答案个数为log2n。
#include<cstring> #include<iostream> #include<cctype> #include<cstdio> #include<algorithm> using namespace std; inline int read() { register int X=0;register char ch=0; for(;!isdigit(ch);ch=getchar()); for(;isdigit(ch);ch=getchar()) X=(X<<3)+(X<<1)+ch-'0'; return X; } inline void write(int x) { if(x>9) write(x/10); putchar(x%10+'0'); } int n,ans,b[100],m; int main() { n=read(); m=n; while(m>>=1) ans++; m=ans+1,ans=0; while(n) { b[m-(++ans)]=(n&1 ? (n>>1)+1 : n>>1); n>>=1; } write(ans),putchar('\n'); for(int i=0;i<ans;i++) write(b[i]),putchar(' '); }
忘开longlong,忘用逆元,忘删调试信息,瞬间爆炸