CSP-S D1T1 题解
咕咕咕的Day1过去了
我的做法
通过手动计算,我画出了\(n=4\)时候的这张表格:
(请注意:本表格倒序存放)
第4位 | 第3位 | 第2位 | 第1位 |
---|---|---|---|
0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 |
1 | 1 | 0 | 0 |
0 | 1 | 0 | 0 |
0 | 1 | 1 | 0 |
1 | 1 | 1 | 0 |
1 | 0 | 1 | 0 |
0 | 0 | 1 | 0 |
0 | 0 | 1 | 1 |
1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 |
0 | 1 | 1 | 1 |
0 | 1 | 0 | 1 |
1 | 1 | 0 | 1 |
1 | 0 | 0 | 1 |
0 | 0 | 0 | 1 |
在这张表格里,我发现了这些规律:
- \(n\leq 4\)时,数据都是本表格的一部分,如:\(n=2\)时是前\(2 \times 2^2\)格,\(n=3\)时是前\(2 \times 2^3\)格
- \(n\)每增加1,相当于把表格前三列向下翻转,然后在最后一列前半部分添加1,后半部分添加0,具体过程如下
(这是我一开始找到的规律,打算开始模拟,然鹅我发现)
(来了来了)对于寻找序列里第\(t\)个(为了描述方便我们从把编号改为\(1-2^n\)),定义\(l=1,r=2^n\),显然\(mid=\frac{l+r}{2}\)(按照C++,这里\(mid\)应该比真实的平均值少0.5,所以会出现最后判断不停止的情况,我的做法是加上0.5,让它一直保持在中间,不知道想的是否全面),加完0.5以后得到的\(mid\)与\(p\)比较,如果小于那么所输出数的第一位一定是0,否则是1
就在我这样写完之后,试了一组小样例发现不对!因为什么呢?因为当第一位是1时,后面的一组数据会是1在前,0在后,于是有了下面这一段代码:
long long p=k+1;
long long tot=quick_pow(2,n);
long long l=1,r=tot;
int y=n;
bool ishang=1;
while(y--){
double mid=(l+r)/2;
if(p<mid+0.5){
if(y==n) printf("0"),ishang=1;
else if(ishang) printf("0");
else if(!ishang) printf("1"),ishang=1;
r=mid;
}
if(p>mid+0.5){
if(y==n) printf("1"),ishang=0;
else if(!ishang) printf("0");
else if(ishang) printf("1"),ishang=0;
l=mid;
}
}
(自认为)复杂度可以达到\(O(n)\),虽然咕咕了(莫名自信)
Day2跟着混吧,没什么打算
代码贴上,欢迎质疑
(对了我还是一个骗分的小宝宝)
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
long long k;
int n;
int h[70][50000];
int ansd[70];
int cnt=3;
long long quick_pow(long long a,long long b){
if(b==1){
return a;
}
else if(b%2==0){
b/=2;
return quick_pow(a,b)*quick_pow(a,b);
}
else{
b/=2;
return quick_pow(a,b)*quick_pow(a,b)*a;
}
}
int main(){
// freopen("code.in","r",stdin);
// freopen("code.out","w",stdout);
scanf("%d%lld",&n,&k);
h[1][1]=0,h[2][1]=0,h[3][1]=0;
h[1][2]=1,h[2][2]=0,h[3][2]=0;
h[1][3]=1,h[2][3]=1,h[3][3]=0;
h[1][4]=0,h[2][4]=1,h[3][4]=0;
h[1][5]=0,h[2][5]=1,h[3][5]=1;
h[1][6]=1,h[2][6]=1,h[3][6]=1;
h[1][7]=1,h[2][7]=0,h[3][7]=1;
h[1][8]=0,h[2][8]=0,h[3][8]=1;
if(n==1){
if(k==1)printf("1\n");
else printf("0\n");
return 0;
}
else if(n==2){
for(int i=n;i>=1;i--){
printf("%d",h[i][k+1]);
}
printf("\n");
return 0;
}
else if(n==3){
for(int i=n;i>=1;i--){
printf("%d",h[i][k+1]);
}
printf("\n");
return 0;
}
else {
long long p=k+1;
long long tot=quick_pow(2,n);
long long l=1,r=tot;
int y=n;
bool ishang=1;
while(y--){
double mid=(l+r)/2;
if(p<mid+0.5){
if(y==n) printf("0"),ishang=1;
else if(ishang) printf("0");
else if(!ishang) printf("1"),ishang=1;
//printf("0");
r=mid;
}
if(p>mid+0.5){
if(y==n) printf("1"),ishang=0;
else if(!ishang) printf("0");
else if(ishang) printf("1"),ishang=0;
l=mid;
}
}
}
printf("\n");
return 0;
}