【数学】省选四校联考 D1T1考考试

在这里插入图片描述


分析:

显然,一个萌的数,必然满足其所有的后缀都是萌的数。

所以,我们可以通过不停地在最高位加值来得到新的萌数。

还有一个结论:
设这个萌的数表示为: A k A k − 1 A k − 2 … … A 0 A_kA_{k-1}A_{k-2}……A_0 AkAk1Ak2A0
则其必然满足:
A k ∗ ( 1 0 k − 2 k ) + A k − 1 ∗ ( 1 0 k − 1 − 2 k − 1 ) + … … + A 0 ∗ ( 1 0 0 − 2 0 ) = 0   ( m o d   2 k + 1 ) A_k*(10^k-2^k)+A_{k-1}*(10^{k-1}-2^{k-1})+……+A_0*(10^0-2^0)=0\ (mod\ 2^{k+1}) Ak(10k2k)+Ak1(10k12k1)++A0(10020)=0 (mod 2k+1)

A k ∗ 2 k ∗ ( 5 k − 1 ) + A k − 1 ∗ 2 k − 1 ∗ ( 5 k − 1 − 1 ) … … + A 0 ∗ 2 0 ∗ ( 5 0 − 1 ) = 0 ( m o d   2 k + 1 ) A_k*2^k*(5^k-1)+A_{k-1}*2^{k-1}*(5^{k-1}-1)……+A_0*2^0*(5^0-1)=0(mod\ 2^{k+1}) Ak2k(5k1)+Ak12k1(5k11)+A020(501)=0(mod 2k+1)
5 k − 1 5^k-1 5k1必然含有4这个因数 ( 5 k − 1 = ( 5 0 + 5 1 + 5 2 + … … + 5 k − 1 ) ∗ 4 ) (5^k-1=(5^0+5^1+5^2+……+5^{k-1})*4) (5k1=(50+51+52++5k1)4)

所以 A k ∗ 2 k + 2 ∗ ( … … ) + A k − 1 ∗ 2 k + 1 ∗ ( … … ) + … … = 0 ( m o d   2 k + 1 ) A_k*2^{k+2}*(……)+A_{k-1}*2^{k+1}*(……)+……=0(mod\ 2^{k+1}) Ak2k+2()+Ak12k+1()+=0(mod 2k+1)

换言之,最高位对其合法性不造成影响

因此,不需要先加入再判断,直接判断当前合不合法,然后最高位分别加0或1即可。

关于如何判断合不合法。。。直接高精暴力取模即可。。。。(因为能询问到的最大的萌数也不超过200位。。。我怎么知道这个结论啊喂)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 100010
using namespace std;
struct BigInt{
	char a[MAXN];
	short int len;
	void add(int pos){
		a[pos]=1;
		len=pos;
	}
	void div2(){
		int les=0;
		for(int i=len;i>=0;i--){
			les=les*10+a[i];
			a[i]=les/2;
			les%=2;
		}
		while(a[len]==0)
			len--;
	}
	void Print(){
		for(int i=len;i>=0;i--)
			PF("%d",a[i]);	
	}
}tmp;
bool Modulo2k(BigInt a,int k){
	while(k){
		a.div2();
		k--;	
	}
	return a.a[0]&1;
}
vector<BigInt> now,add1,add0;
int main(){
	freopen("quiz.in","r",stdin);
	freopen("quiz.out","w",stdout);
	int n;
	SF("%d",&n);
	now.push_back(tmp);
	int len=0;
	while(1){
		for(int i=0;i<now.size();i++)
			if(Modulo2k(now[i],len)==0){
				tmp=now[i];
				add0.push_back(tmp);
				tmp.add(len);
				add1.push_back(tmp);
				n--;
				if(n==0){
					tmp.Print();
					return 0;
				}
			}
		now.clear();
		for(int i=0;i<add0.size();i++)
			now.push_back(add0[i]);
		for(int i=0;i<add1.size();i++)
			now.push_back(add1[i]);
		add0.clear();
		add1.clear();
		len++;
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值