#数位dp,高精度#洛谷 2235 [HNOI2002]Kathy函数

题目


分析

首先这个\(f\)函数其实求的是二进制下的回文数,简单证明一下
\(n\)在二进制下的回文数为\(n'\),第一二条显然
第三条\(f(2n)=f(n)\Rightarrow \overline {0} n'=n'\),很好证明
第四条\(f(4n+1)=2f(2n+1)-f(n)\Rightarrow \overline {10}n'=\overline{1}n'\overline{0}-n'=\overline{10}n'\)
第五条

\[f(4n+3)=3f(2n+1)-2f(n)=2(2f(2n+1)-f(n))-f(2n+1)=2f(4n+1)-f(2n+1) \]

\[\Rightarrow\overline{11}n'=\overline{10}n'\overline{0}-\overline{1}n'=\overline{11}n' \]

得证,对于位数小于\(n\)的位数答案,易求
对于位数等于\(n\)的位数的答案,特判\(n\)是否为回文数
给出一个伪代码

inline bool mxcheck(lll m,lll len){
    rr int j=len/2,i=len-j-1;
	for (;i>=0&&j<len;--i,++j){
		if (((m>>i)&1)>((m>>j)&1)) return 1;
		if (((m>>i)&1)<((m>>j)&1)) return 0;
	}
	return 1;
}
signed main(){
    scanf("%lld",&m);
	for (len=1,n=1;n<m;++len,n=n<<1|1)
	    ans+=1ll<<((len-1)/2);
	ans+=(m&(n>>1))>>(len>>1);
	if (mxcheck(m,len)) ++ans;
	printf("%lld\n",ans);
}

改成高精度就可以A了


代码

#include <cstdio>
#include <cctype>
#define rr register
#define mod 1000000000
using namespace std;
int len,Ans,a[351],ans[351],Q[101],Qlen;
inline void add_one(int *a,int now,int &len){//在二进制的某一位加1
	for (;a[now];++now) a[now]=0; a[now]=1;
	if (now>=len) len=now+1;
}
inline bool mxcheck(){
	rr int j=len/2,i=len-j-1;
	for (;i>=0&&j<len;--i,++j)
		if (a[i]!=a[j]) return a[i]>a[j];
	return 1;
}
inline void innput(){
	rr char c=getchar();
	for (;!isdigit(c);c=getchar());
	for (;isdigit(c);c=getchar()){
		rr int w=c^48,t=0;
		if (len){
			len+=3;
			for (rr int j=len-1;~j;--j){
				a[j]=0;
				if (j>=3&&a[j-3]) add_one(a,j,len);
				if (j>=1&&a[j-1]) add_one(a,j,len);
			}
		}
		for (;w;w>>=1,++t) if (w&1) add_one(a,t,len);
	}	
}
signed main(){
	innput();
	for (rr int i=0;i<len-1;++i)
	    add_one(ans,i>>1,Ans);
	for (rr int i=len/2,j=0;i<len-1;++i,++j)
	    if (a[i]) add_one(ans,j,Ans);
	if (mxcheck()) add_one(ans,0,Ans);
	for (rr int i=Ans-1;~i;--i){//将二进制转换为十进制
		rr int g=0;
		for (rr int j=0;j<Qlen;++j){
			rr int s=Q[j]*2+g;
			g=s/mod,Q[j]=s%mod;
		}
		if (g) Q[Qlen++]=g;
		g=ans[i]; rr int t=0;
		for (;g;++t) g=(++Q[t])/mod;
		if (t>Qlen) Qlen=t;
	}
	printf("%d",Q[Qlen-1]);
	for (rr int i=Qlen-2;~i;--i) printf("%09d",Q[i]);
	return 0;
}
posted @ 2020-08-18 20:30  lemondinosaur  阅读(123)  评论(0编辑  收藏  举报