求x的每一位平方和乘c==x(打表,降低复杂度)

这篇博客介绍了ACM竞赛中的一道题目,要求找出在[a, b]区间内,满足每一位数字平方和乘以c等于原数的整数x的数量。通过分析,将复杂度从1e9/c * 9降低到1e9/100 * 9,通过预计算c在1~100范围内的合法解来进一步优化解决方案。" 137215363,22822209,Android开发:Profiler-Energy能耗分析详解,"['Android开发', '能耗分析']
摘要由CSDN通过智能技术生成

ACM:https://blog.csdn.net/weixin_39778570/article/details/83187443
题目:https://nanti.jisuanke.com/t/38090

输入三个数 a,b,c,输出 [a,b] 这b−a+1 个整数中,有多少个整数 x 满足,x 每一位的平方和 ×c=x
其中 a,b,c 都不超过10^9
Input
三个正整数 a,b,c,意义见题面。
Output
一个整数(没有输出 0),意义见题面。

分析:
s u m ∗ c = t ⇒ s u m = t / c sum*c=t ⇒ sum=t/c sumc=tsum=t/c
我们可以找到[a,b]范围中是c的倍数的数就行那么复杂度可以降到 1 e 9 / c ∗ 9 1e9/c*9 1e9/c9,
但是这样做复杂度还是太高了,对于c比较小的话。
然后我试试把 [ 1 , 1 e 9 ] [1,1e9] [1,1e9]中c比较小合法数生成出来,结果发现数很少,于是我把c为1~100的合法数都打表
复杂度就降到 1 e 9 / 100 ∗ 9 1e9/100*9 1e9/1009啦…

#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
int a,b,c,t,ans;
int d[10] = {0,1,4,9,16,25,36,49,64,81};
int mp[101][11] ={
	{0},{1,},
	{50,298,},
	{267,},
	{376,},
	{20,},
	{372,480,},
	{133,917,973,},
	{360,},
	{315,},
	{10,},
	{550,803,},
	{240,},
	{130,},
	{532,630,1148,},
	{1290,},
	{2688,},
	{1547,2669,2958,},
	{2196,},
	{},
	{500,2980,},
	{420,1071,2268,},
	{1364,1606,},
	{},
	{120,},
	{400,2575,},
	{},
	{},
	{1316,},
	{},
	{2670,},
	{310,3906,},
	{1344,5696,},
	{},
	{1700,},
	{2660,3290,},
	{},
	{111,6179,},
	{},
	{},
	{3760,},
	{8938,},
	{210,1134,3108,},
	{},
	{2552,3256,},
	{5490,},
	{2254,},
	{2444,},
	{9936,},
	{},
	{200,},
	{4080,7293,7854,7905,},
	{},
	{1431,},
	{},
	{110,1430,6930,},
	{2352,5208,6328,},
	{8664,},
	{},
	{8083,},
	{3720,4800,},
	{},
	{},
	{},
	{4416,8256,},
	{2600,},
	{},
	{},
	{3060,6800,},
	{3450,},
	{1330,9170,9730,},
	{3053,},
	{6624,},
	{13797,},
	{5550,8362,},
	{8550,},
	{},
	{},
	{10686,12948,},
	{},
	{3600,},
	{2511,},
	{},
	{},
	{18984,},
	{},
	{8600,},
	{4350,18966,},
	{},
	{},
	{3150,},
	{},
	{17848,},
	{1302,12927,},
	{1222,},
	{},
	{10944,17088,},
	{18818,},
	{},
	{},
	{100,}
};
// 打表 
void get(){
	a=1;
	b=1000000000;
	for(int c=1; c<=100; c++){
		ans=0;
		if(a%c==0)t=a;
		else t = a+(c-a%c);
		int i = t/c;
		cout<<"{"; 
		for(; t<=b; t+=c,i++){
			int x = t,now=0;
			while(x){
				now+=d[x%10];
				if(now>i)break;
				x/=10;
			}
			if(now==i)cout<<t<<',';
			if(now==i)ans++;
		}
	//	if(ans)cout<<"乘数:"<<c<<endl;
		cout<<"},"<<endl; 
	//	cout<<ans<<endl;
	}
} 
int main(){
//	get();
	cin>>a>>b>>c;
	ans =0;
	if(c>=1&&c<=100){
		fo(i,0,5){
			if(mp[c][i]>=a&&mp[c][i]<=b)ans++;
		}
		cout<<ans<<endl;
		return 0;
	}
	if(a%c==0)t=a;
	else t = a+(c-a%c);
	int i = t/c;
	for(; t<=b; t+=c,i++){
		int x = t,now=0;
		while(x){
			now+=d[x%10];
			if(now>i)break;
			x/=10;
		}
//		if(now==i)cout<<t<<endl;
		if(now==i)ans++;
	}
//	if(ans)cout<<"乘数:"<<c<<endl;
	cout<<ans<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值