2021级ACM第二学期第五次热身赛 ---A题一道简单的题

题目大意

给定一个数,在恰好修改某一位的情况下使修改后的数字成为某个数的平方。问有多少种修改方式。

题目思路

每一位有至多9种修改方式,n的最多只有4位。因此我们只需要在最外层枚举每一位,第二层枚举0-9的数字,共枚举十次,对于首位要进行特判,如果是首位且第二层修改后的数字是0,则不修改;或者n该位原本的数字与第二层修改后的数字一致,也不进行修改。最后当第二层的数字符合修改条件后,进入第三层循环枚举位数,将新数字组装起来,判断他开根号是否为正整数,若为正整数则符合要求,否则不符合。

由于数据量比较大,t 最大为10^6,我们若对于每个n都进行三层循环去找的话,时间复杂度可高达 4*10*4*10^6 = 1.6*10^8 会超时。这个时候我们可以想到用打表的方式去处理,先将1000-9999的这近10000个数字进行处理存入数组。然后每个n直接输出已经存下来了的答案即可,时间复杂度为 4*10*4*10^4 + 1.0*10^6 = 2.6*10^6。

参考代码

#include<bits/stdc++.h>
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
const ll mod = 998244353;
using namespace std;
int b[20000];
int a[10];
void pre() { //打表处理
	for (int l = 1000; l <= 9999; l++) {
		int ans = 0; //该数字的位数
		int n = l;
		while (n) {
			a[++ans] = n % 10;
			n /= 10;
		}
		int sum = 0;
		for (int i = ans; i >= 1; i--) { // 枚举每一位
			for (int j = 0; j <= 9; j++) { // 枚举修改后的数字
				if ((j == 0 && i == ans) || j == a[i]) {
					continue;//若当前为首位且为0或者当前位原来的数字和修改后的数字一致,不符合要求
				}
				int temp = 0;//新数字
				for (int k = ans; k >= 1; k--) {
					if (i == k) { //若该位是修改的位置,则拼接的是新数字j
						temp = temp * 10 + j;
					}
					else {
						temp = temp * 10 + a[k];
					}
				}
				if (!fmod(sqrt(temp * 1.0), 1)) {//若新数字开根号是整数则方案数加一
					sum++;
				}
			}
		}
		b[l] = sum;//记录
	}
}
int main() {
	int t;
	cin >> t;
	pre();
	while (t--) {
		int n;
		cin >> n;
		cout << b[n] << endl;
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值