1. 2067: [蓝桥杯2023初赛] 幸运数
传送门:http://oj.ecustacm.cn/problem.php?id=2067
1.1. 题意
小蓝认为如果一个数含有偶数个数位,并且前面一半的数位之和等于后面一半的数位之和,则这个数是他的幸运数字。 例如 是一个幸运数字,因为它有 个数位,并且 。 现在请你帮他计算从 至 之间共有多少个不同的幸运数字。 本题的结果为一个整数,在提交答案时只输出这个整数,输出多余的内容将无法得分。
1.2. Tag
模拟、枚举
1.3. 难度
☆
1.4. 思路1
直接从枚举到,每个数字判断两个条件:
偶数个数位
前半数位和等于后半数位和
数字拆分出每一位可以通过不断对求余数求解。
例如:、、、、...
这样就能求出每一位然后进行判断。
1.4.1. C++:
#include<bits/stdc++.h>
using namespace std;
inline bool check(int x){
string s;
while(x)s += (char)(x % 10 + '0'), x /= 10;
int n = s.size();
if(n % 2 == 1)return false; //约束1:偶数个数位
int sum1 = 0, sum2 = 0;
for(int i = 0; i < n / 2; i++){
sum1 += s[i] - '0';
sum2 += s[i + n / 2] - '0';
}
return sum1 == sum2; //约束2:前半部分和等于后半部分
}
int main(){
// int ans = 0;
// for(int i = 1; i <= 100000000; i++){
// if(check(i)){
// ans++;
// //cout<<i<<endl;
// }
// }
// cout<<ans<<endl;
cout<<4430091<<endl;
return 0;
}
1.4.2. Java:
import java.util.*;
public class Main {
public static void main(String[] args) {
// int ans = 0;
// for(int i = 1; i <= 100000000; i++){
// if(check(i))ans++;
// }
int ans = 4430091;
System.out.println(ans);
}
public static boolean check(int x) {
String s = String.valueOf(x);
if(s.length() % 2 == 1)return false;
int sum1 = 0, sum2 = 0;
for(int i = 0; i < s.length() / 2; i++){
sum1 += s.charAt(i) - '0';
sum2 += s.charAt(i + s.length() / 2) - '0';
}
return sum1 == sum2;
}
}
1.4.3. Python:
def check(x):
x = [int(i) for i in list(str(x))]
n = len(x)
if n % 2 == 1:
return False
return sum(x[:n // 2]) == sum(x[n // 2:])
# ans = 0
# for i in range(10, 100000001):
# if check(i):
# ans += 1
# print(ans)
print(4430091)
1.5. 思路2
统计位数相同且和相同的数字个数记为表。
表示位数中,和为的数字个数。
对于位数为的数字,前半部分和为存在种可能。
后半部分和为存在种可能(因为后半部分允许存在前导0)。
最终答案等于
1.5.1. C++
#include<bits/stdc++.h>
using namespace std;
int A[5][50];
int main(){
for(int x = 1; x <= 9999; x++){
int now_cnt = 0, now_sum = 0;
int now = x;
while(now)now_cnt++, now_sum += now % 10, now /= 10;
A[now_cnt][now_sum]++;
}
int ans = 0;
for(int i = 1; i <= 4; i++)
for(int j = 1; j <= i * 9; j++)
for(int k = 1; k <= i; k++)
ans += A[i][j] * A[k][j];
cout<<ans<<endl;
return 0;
}
1.5.2. Java
import java.util.*;
public class Main {
public static void main(String[] args) {
int[][] A = new int[5][50];
for(int x = 1; x <= 9999; x++){
int now_cnt = 0, now_sum = 0;
int now = x;
while(now != 0){
now_cnt++;
now_sum += now % 10;
now /= 10;
}
A[now_cnt][now_sum]++;
}
int ans = 0;
for(int i = 1; i <= 4; i++)
for(int j = 1; j <= i * 9; j++)
for(int k = 1; k <= i; k++)
ans += A[i][j] * A[k][j];
System.out.println(ans);
}
}
1.5.3. Python
A = [[0] * 50 for i in range(5)]
idx = 0
for x in range(1, 10000):
x = [int(i) for i in list(str(x))]
A[len(x)][sum(x)] += 1
ans = 0
for i in range(1, 5):
for j in range(1, i * 9 + 1):
for k in range(1, i + 1):
ans += A[i][j] * A[k][j]
print(ans)
1.6. 思考
如果求中的幸运数个数,其中应该怎么做呢?