Processing math: 0%

[CSP校内集训]A(进制)

题意

给一个数S,可以加a或者乘b,问最少多少次操作到T,无解输出-1,(1\leq a\leq 10^9,2\leq b\leq 10^9)

思路

刚刚看到像跳楼机,但是a,b较大于是放弃(说不定可以乱胡呢?);当然直接建图也有30分的好成绩(

即使a,b交替操作,最终状态仍然可以化成T=S\times b^y + a\times x的形式

枚举y,最多不超过logn种,一个y对应一个x,需要对x进行b+1进制拆分,且每一位加起来的数最小

从高位到低位贪心即可完成拆分操作,整个算法的时间复杂度为O(log^2n)maybe

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll s,t,a,b,ans=(1LL<<60);

ll qpow(ll a,ll b)
{
	ll ret=1;
	while(b)
	{
		if(b&1) ret=ret*a;
		a*=a;
		b>>=1;
	}
	return ret;
}
ll find(ll x,ll y)
{
	ll ret=0;
	for(int i=x;i>=0;--i)
	{
		ll po=qpow(b,i);
		ret+=y/po;
		y%=po;
	}
	return ret;
}
int main()
{
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	scanf("%lld%lld%lld%lld",&s,&t,&a,&b);
	for(ll i=0;i<=32;i++)
	{
		ll x=t-s*qpow(b,i);
		if(x<0) break;
		if(x%a) continue;
		ll need=x/a;
		ll st=find(i,need);
		if(st) ans=min(ans,i+st);
	}
	if(ans==(1LL<<60)) ans=-1;
	printf("%lld\n",ans);
	return 0;
}
posted @   擅长平地摔的艾拉酱  阅读(181)  评论(0编辑  收藏  举报
编辑推荐:
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
阅读排行:
· C# 13 中的新增功能实操
· Ollama本地部署大模型总结
· 2025成都.NET开发者Connect圆满结束
· langchain0.3教程:从0到1打造一个智能聊天机器人
· 用一种新的分类方法梳理设计模式的脉络
/*取消选中*/
点击右上角即可分享
微信分享提示