2004年的论文《优化,再优化》
中所讨论的题的加强版(其实并没有加强多少……);
论文最后给出了
n−√
的复杂度;
其实可以用生成函数给出一种
logn
的做法,而且更加清晰;
首先有递推式:
g(i,j)=g(i−1,j)+g(i−1,j−1)+1
g(1,j)=1
1<i,j
(可参考论文)
写成生成函数;
f1(x)=11−x−1=x1−x
fj(x)=(1+x)fj−1(x)+x1−x
解得:
fj(x)=(1+x)j1−x−x1−x
再变回我们所熟悉的;
g(i,j)=Σjk=0Ckj−1
然后就可以做啦.但细节一大堆(参考代码)…
其实这题本质上就是一个猜数问题是模型王子的弱化版;
只是条件弱化带来了更多性质;
最后很无耻的要到了数据…
#include<bits/stdc++.h>
#define rep(i,k,n) for(int i=k;i<=n;i++)
using namespace std;
typedef long long ll;
const ll lim=4294967296;
const int N=1e4+7;
const int M=100;
ll C[N][105];
int T,F,n,b;
void init(){
C[0][0]=1;
rep(i,1,N-1){
C[i][0]=1;
rep(j,1,M)C[i][j]=C[i-1][j-1]+C[i-1][j],C[i][j]=min(C[i][j],lim);
}
rep(i,1,N-1){
rep(j,1,M)C[i][j]+=C[i][j-1],C[i][j]=min(C[i][j],lim);
}
}
ll solve1(){
if(n<N){
if(b>M || C[n][b]>=lim)return -1;
return C[n][b]-1;
}
else{
if(b==1)return n;
else if(b==2){
ll ans=(1ll*n*n+1ll*n)/2ll;
if(ans>lim)return -1;
return ans;
}else return -1;
}
}
int solve2(){
if(F>=N){
if(b==1)return F;
else if(b==2){
int l=1,r=F;
while(l<r){
int x=(l+r)>>1;
if(1ll*x*x+1ll*x<2ll*F)l=x+1;
else r=x;
}
return l;
}
}
rep(i,1,N-1)if(C[i][min(i,b)]-1>=F)return i;
return -1;
}
int solve3(){
if(n<N){
rep(i,1,b)if(C[n][i]-1>=F)return i;
return -1;
}else{
if(n>=F-1)return 1;
else if(1ll*n*n+1ll*n-2ll>=2ll*F)return 2;
else return 3;
}
}
int main(){
init();
scanf("%d",&T);
rep(t,1,T){
scanf("%d%d%d",&F,&n,&b);b=min(b,n);
printf("Case #%d: %lld %d %d\n",t,solve1(),solve2(),solve3());
}
}