1. 迫真数论
题目描述
H君有一天出门的时候也许是因为过于疲惫,不幸追尾了一辆黑色高级轿车,车主提出的和解条件是…解答一个数论难题!H君一秒钟就搞到了答案,但是想要保护后辈的您决定帮H君回答这个问题:
车主定义了一个函数 f(x)f(x) 表示正整数 xx 的各数位之和,举例来说,f(114514) = 1+1+4+5+1+4=16f(114514)=1+1+4+5+1+4=16。
现在将有 qq 次询问,每次询问给出一个数 n ,您需要回答 n 的约数中有多少个数 x 满足 f(x)=⌊ x/2⌋ 。
输入描述
第一行一个数 qq ,表示询问次数。
接下来 qq 行,每行一个数 nn。
数据范围:
1<= n<=1018, 1 <=q <= 105 。
输出描述
共 q 行,每一行为给出的 n 的约数中满足条件的数的个数。
解析:
容易发现满足 f(x) = ⌊x2⌋ 的正整数 x 只有 17, 18,证明如下。
∵ f(x) = ⌊x2⌋
∴ 2f(x) = x or 2f(x) + 1 = x
设 n 为满足上述条件的数
由 n 的位数考虑:
• n 只有一位:设 x = a,则 2a = a or 2a + 1 = a,显然 a 没有 [1, 9] 间
的整数解
• n 有两位:设 x = 10a + b(即 a 是十位, b 是个位),则 2a + 2b =
10a + b or 2a + 2b + 1 = 10a + b
∴ 8a − b = 0 or 8a − b − 1 = 0
∴ a = 1, b = 8 or a = 1, b = 7
∴ n = 18 or n = 17
• n 有三位:设 x = 100a + 10b + c(即 a 是百位, b 是十位, c 是个位),
则 2a + 2b + 2c = 100a + 10b + c or 2a + 2b + 2c + 1 = 100a + 10b + c
∴ 98a + 8b − c = 0 or 98a + 8b − c − 1 = 0
∵ a ≥ 1, b ≥ 1(a 是百位, b 是十位)
∴ c ≥ 108
不满足 c ∈ [1, 9](c 是个位),故该情况不成立
• 大于三位的,与三位类似,都与个位 ∈ [1, 9] 不符
综上,满足 f(x) = ⌊x2⌋ 的正整数仅有 17, 18。
对于一组询问,判断 17 和 18 是否是 n 的约数即可。
代码实现
public class 迫真数论 {
private static Scanner cin = new Scanner(System.in);
private static PrintWriter out = new PrintWriter(System.out);
public static void main(String[] args) {
int t = cin.nextInt();
int ans = 0;
while (t-->0) {
BigInteger num = cin.nextBigInteger();
ans = 0;
if (num.mod(BigInteger.valueOf(18)) == BigInteger.ZERO) {
ans++;
}
if (num.mod(BigInteger.valueOf(17)) == BigInteger.ZERO) {
ans++;
}
System.out.println(ans);
}
}
}
#include<iostream>
using namespace std;
int main() {
int t;
cin >> t;
int ans;
while (t--) {
long long n;
cin >> n;
ans = 0;
if (n%18L == 0) {
ans++;
}
if (n%17L == 0) {
ans++;
}
cout << ans << endl;
}
}