1. 程式人生 > >數學找規律 number

數學找規律 number

題幹去內網找。。。
計算方法是可以通過找規律的方法找出來的,但是正規的式子是
f(i, k) = ∑(x=1,x<=mid(k,p))C(ax+1,k-x+1)-C(ax,k-x+1)
其中:p表示i在二進位制下1的個數,ax表示二進位制下第x高的1所在為代表的2的冪次。
可以證明出f(i.k)<=f(i+1,k).因此滿足的答案連成一串。
特判k==1:此時有無限多。
其他只要二分出邊界即可。

#pragma GCC optimize("O3")
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream> #include<algorithm> #include<cmath> #define inf 1e18 #define ll unsigned long long using namespace std; int t,k;ll m,c[70][70]; void init() { c[1][1]=1; for(int i=2;i<=65;i++) for(int j=1;j<=i;j++) c[i][j]=c[i-1][j-1]+c[i-1][j]; } ll check(ll x) { int
p=0,zhan[70],h=0;ll j,s=0; for(j=x;j>0;j-=j&-j) zhan[++p]=log2(j&-j); j=0; while(p) { s+=c[zhan[p]+1][k-j]; j++;p--; if(k-j==0)break; } return s; } int main() { cin>>t; init(); while(t--) { scanf("%lld%d",&m,&k); if
(k==1){printf("-1\n");continue;} if(k==64){printf("1 9223372036854775807\n");continue;} ll l=1,r=9223372036854775807LL,mid,ans1,ans2; while(l<=r) { mid=(l+r)>>1; if(check(mid)<m)l=mid+1; else r=mid-1; } ans1=r+1; printf("%lld ",ans1); l=1,r=9223372036854775807LL; while(l<=r) { mid=l+r>>1; if(check(mid)<=m)l=mid+1; else r=mid-1; } ans2=l-1; printf("%lld\n",ans2); } }