EOJ Monthly 2019.5 (based on May Selection) B.幂运算

在这里插入图片描述
在这里插入图片描述
这题是一道不容易写的数学题,并且题目只给了1s,就是说O(n)的算法都会T(我T了无数发),这时我们就要从别的方向考虑了。

我们发现a,b,c,d都是在1e9范围内的,就是说如果我们把a和c看成x ^ k1和x ^ k2,那么k1,k2<=32,这下子我们的运算量一下就小下来了。
题目要求的是a ^ b = c ^ d,我们把a,c按照上面那样处理,变成x ^ k1和x ^ k2,这样最后的式子就是x ^ (k1b)= x ^ (k2d)——>k1b = k2d。

最后答案由两部分组成:
平凡的情况:a=c,b=d 。
其他的情况:a≠c,就必须满足 k1 * b = k2 * d,为保证不重复计数,我们必须满足gcd(k1,k2)=1,然后我们跑两个(1,32)的 for 循环,再对每个满足条件的答案进行处理,这题也就不那么难了。

我这种做法的时间复杂度大概是O(32 * 32 * log n),但是好像别人有O(2 * 32 * log n)
的做法……

#include<bits/stdc++.h>
using namespace std;
#define maxn 300005
#define ll long long

const ll mod=1e9+7;
ll a,b,c,d;

ll poww(ll a,ll b){
    ll ans=1,base=a;
    while(b!=0){
        if(b&1!=0)ans=ans*base;
        base=base*base;
        b>>=1;
    }
    return ans;
}

int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		scanf("%lld %lld %lld %lld",&a,&b,&c,&d);
		ll ans=b*d;
		for(int i=1;i<=32;i++)
			for(int j=1;j<=32;j++){
				if(__gcd(i,j)!=1)continue;
				ll A=pow(a,1.0/i);
				ll C=pow(c,1.0/j);
				while(poww(A,i)<=a)
					A++;
				while(poww(C,j)<=c)
					C++;
				A--;C--;
	            ans+=min(A-1,C-1)*min(b/j,d/i);
	            ans%=mod;
			}
		printf("%lld\n",ans);
	}
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值