ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

luogu P8350 [SDOI/SXOI2022] 进制转换

2022-09-09 20:02:05  阅读:198  来源: 互联网

标签:SXOI2022 int luogu ll B1 P8350 using op define


题面传送门

首先题面中那个\(y=1\)的数位dp部分分是诈骗,这题和数位dp没有半毛钱关系。

为啥SDOI两个T2都是算法诈骗题啊

首先考虑一个爆搜,爆搜三进制每一位是什么,然后转化成二进制。这个复杂度显然是\(O(n)\)的,不可接受。

但是实际上可以优化,我们考虑对于一个较低位的三进制数,其能影响的二进制的最高位数有限,因此考虑根号分治。设定阈值\(B1,B2\)表示三进制下除了后\(B1\)位外的数爆搜,后\(B1\)位的数只会影响二进制下\(B2\)范围内的数。后面就可以有\(O(B2\log n)\)的dp可以解决。

实际实现的时候取\(B1=13,B2=21\)即可,时间复杂度差不多是\(O(\sqrt n)\),但是跑得非常慢。

code:

#include<bits/stdc++.h>
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((m)*(x-1)+(y))
#define R(n) (rnd()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using ll=long long;using db=double;using lb=long db;using ui=unsigned;using ull=unsigned ll;
using namespace std;const int N=(1<<21)+5,M=13,M1=pow(3,13),M2=28,K=1e5+5,mod=998244353,Mod=mod-1;const db eps=1e-5;const int INF=1e9+7;
int X,Y,z,A[30];ll f[N][2][2],g[N][2][2],Po[30],Z[3],n,Ps[30][3],Ans,Ys[30];
ll mpow(ll x,ll y=mod-2){ll Ans=1;while(y) y&1&&(Ans=Ans*x%mod),y>>=1,x=x*x%mod;return Ans;}
void calc(ll w,int op,ll Ts){int i,p=w&((1<<21)-1);f[p][op][0]=(f[p][op][0]+Ts*Ys[__builtin_popcount(w>>21)])%mod;f[p][op][1]=(f[p][op][1]+Ts*Ys[__builtin_popcount((w>>21)+1)])%mod;}
void dfs(int x,ll w,int op,ll Ts){if(x==12) return calc(w,op,Ts);for(int i=0;i<=(op?A[x]:2);i++) dfs(x-1,w+Po[x-1]*i,i==A[x]&&op,Ts*Ps[x][i]%mod);}
int main(){
	freopen("1.in","r",stdin);
	int i,j,x,y,op;scanf("%lld%d%d%d",&n,&X,&Y,&z);for(Po[0]=i=1;i<=M2;i++) Po[i]=Po[i-1]*3,A[i]=n%Po[i]/Po[i-1],Ps[i][0]=1,Ps[i][1]=mpow(X,Po[i-1])*z%mod,Ps[i][2]=mpow(X,Po[i-1]*2)*z%mod*z%mod;
	for(Ys[0]=i=1;i<=29;i++) Ys[i]=Ys[i-1]*Y%mod;dfs(M2,0,1,1);for(i=12;i;i--){
		Mc(g,f);Me(f,0);for(j=0;j<(1<<21);j++){
			for(x=0;x<2;x++){
				for(y=0;y<2;y++){if(!g[j][x][y]) continue;if(y&&j+Po[i]-1<(1<<21)) continue;
					for(op=0;op<=(x?A[i]:2);op++){//cerr<<i<<' '<<j<<' '<<x<<" "<<y<<' '<<g[j][x][y]<<'\n';
						if(j+op*Po[i-1]>=(1<<21)) {if(y) f[j+op*Po[i-1]-(1<<21)][x&&op==A[i]][0]=(f[j+op*Po[i-1]-(1<<21)][x&&op==A[i]][0]+g[j][x][y]*Ps[i][op])%mod;}
						else {f[j+op*Po[i-1]][x&&op==A[i]][y]=(f[j+op*Po[i-1]][x&&op==A[i]][y]+g[j][x][y]*Ps[i][op])%mod;}
					}
				}
			}
		}
	}for(i=0;i<(1<<21);i++) for(j=0;j<2;j++)Ans+=f[i][j][0]*Ys[__builtin_popcount(i)]%mod;printf("%lld\n",(Ans-1)%mod);
}

标签:SXOI2022,int,luogu,ll,B1,P8350,using,op,define
来源: https://www.cnblogs.com/275307894a/p/16673818.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有