洛谷P8116 魔理沙的计算器

题目链接:P8116 魔理沙的计算器

大意

给一个 b b b 进制的计算器,但屏幕上只能显示 k k k 位数字,求 b b b 进制下满足 1 ÷ ( 1 ÷ n ) = n 1\div(1\div n)=n 1÷(1÷n)=n n n n 的个数,其中 1 ÷ n 1\div n 1÷n 1 ÷ ( 1 ÷ n ) 1\div(1\div n) 1÷(1÷n) 都使用计算器上显示的值。

题解

赛时就感觉这是个神仙思维题。

首先屏幕上只能显示有限位数字,也就说明如果 1 n \frac{1}{n} n1 是个无限小数是绝无可能满足 1 ÷ ( 1 ÷ n ) = n 1\div(1\div n)=n 1÷(1÷n)=n 的。

这个地方我们形式化描述一下,如果 1 n \frac{1}{n} n1 是个无限小数,设屏幕上显示的 1 ÷ n 1\div n 1÷n n ′ = 0. a 1 a 2 ⋯ a k − 1 n'=0.a_1a_2\cdots a_{k-1} n=0.a1a2ak1,那么因为小数点后第 k k k 位及之后被省去, n ′ n' n 再乘上 n n n 得到的结果相比 1 1 1 一定会在小数点后第 k − 1 k-1 k1 位有缺失。

那么如果在屏幕上显示 1 ÷ n ′ = n 1\div n'=n 1÷n=n 就会出现矛盾。屏幕上显示 n n n 说明 1 ÷ n ′ 1\div n' 1÷n 的结果 n ′ ′ n'' n 至少在小数点后第 k − 1 k-1 k1 位及之前都为 0 0 0,而 n ′ n' n 小于零, n ′ ′ n'' n 小数点后第 k k k 位及以后乘上 n ′ n' n 的贡献显然无法弥补小数点后第 k − 1 k-1 k1 位的缺失。所以上面的结论成立。

举个栗子,假如拿十进制下的 1 ÷ 7 1\div 7 1÷7 在屏幕上得到 0.1428 0.1428 0.1428,会有 0.1428 × 7 = 0.9996 0.1428\times 7=0.9996 0.1428×7=0.9996,在小数点后第 4 4 4 位上就出现了缺失。那么我拿 1 ÷ 0.1428 1\div 0.1428 1÷0.1428 就不可能在屏幕上显示 7 7 7(即除出来的真正结果为 7.0000 ⋯ 7.0000\cdots 7.0000),因为这样的话那 0.0004 0.0004 0.0004 的差距不会被弥补。

(这个地方可能说的有点绕,但理是这么个理。)

那么范围就缩小到所有 b b b 进制下除 1 1 1 能得到有限小数的数。然而又有 k k k 位的限制,这就要求 1 n \frac{1}{n} n1 的小数点后数字位数不能大于 k − 1 k-1 k1 位(因为整数部分也占一位)。

1 ÷ n 1\div n 1÷n 的真实值为 0. c 1 c 2 ⋯ c k − 1 0.c_1c_2\cdots c_{k-1} 0.c1c2ck1,小数部分不足 k − 1 k-1 k1 位的用零补齐。自然想到将 1 1 1 0. c 1 c 2 ⋯ c k − 1 0.c_1c_2\cdots c_{k-1} 0.c1c2ck1 同乘 b k − 1 b^{k-1} bk1,得到 b b b 进制下的 100 ⋯ 0 100\cdots0 1000 c 1 c 2 ⋯ c k − 1 ‾ \overline{c_1c_2\cdots c_{k-1}} c1c2ck1

又由题, b b b 进制下的 c 1 c 2 ⋯ c k − 1 ‾ \overline{c_1c_2\cdots c_{k-1}} c1c2ck1 必然是 100 ⋯ 0 100\cdots0 1000 的一个因子,我们要求的 n n n 的个数实际上就是满足要求的 c 1 c 2 ⋯ c k − 1 ‾ \overline{c_1c_2\cdots c_{k-1}} c1c2ck1 的个数,也即 100 ⋯ 0 [ b ] 100\cdots0_{[b]} 1000[b] 的因子个数。所以将 100 ⋯ 0 [ b ] 100\cdots0_{[b]} 1000[b] 转回十进制得到 b k − 1 b^{k-1} bk1,问题转化为求 b k − 1 b^{k-1} bk1 的因子个数。

这下这个题目就很数学了,直接对 b b b 分解质因数,根据唯一分解定理的推论求因子个数即可。

代码

#include<bits/stdc++.h>
using namespace std;
#define N 100003
#define LL long long
#define INF 0x3f3f3f3f
#define MOD 998244353
int t,b,k;
LL h[N];
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&b,&k);
		LL ans=1;
		int a=b,ct=0;
		for(int i=2;i*i<=b;++i)
			if(a%i==0){
				ct++;
				while(a%i==0) a/=i,h[ct]++;
				h[ct]=h[ct]*(k-1)%MOD;
			}
		if(a>1) h[++ct]=k-1;
		for(int i=1;i<=ct;++i)
			ans=ans*(h[i]+1)%MOD,h[i]=0;
		printf("%lld\n",ans);
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
洛谷p1449是一个C语言题目,要求实现一个后缀表达式的计算器。后缀表达式是一种不使用括号,将运算符号放在运算对象之后的表达式。计算后缀表达式的方法是从左到右遍历表达式,遇到操作数就入栈,遇到运算符就从栈中弹出两个操作数进行运算,然后将结果再次入栈,直到遍历完整个表达式,最后栈中的唯一元素就是计算结果。 以下是一个C语言的示例代码,用于实现后缀表达式的计算器: ```c #include <stdio.h> #include <stdlib.h> #include <ctype.h> #define MAX_SIZE 100 typedef struct { int data[MAX_SIZE]; int top; } Stack; void initStack(Stack *s) { s->top = -1; } void push(Stack *s, int value) { if (s->top == MAX_SIZE - 1) { printf("Stack is full.\n"); exit(1); } s->data[++(s->top)] = value; } int pop(Stack *s) { if (s->top == -1) { printf("Stack is empty.\n"); exit(1); } return s->data[(s->top)--]; } int calculate(int operand1, int operand2, char operator) { switch (operator) { case '+': return operand1 + operand2; case '-': return operand1 - operand2; case '*': return operand1 * operand2; case '/': return operand1 / operand2; default: printf("Invalid operator.\n"); exit(1); } } int evaluatePostfixExpression(char *expression) { Stack stack; initStack(&stack); int i = 0; while (expression[i] != '@') { if (isdigit(expression[i])) { push(&stack, expression[i] - '0'); } else if (expression[i] == '.') { int operand2 = pop(&stack); int operand1 = pop(&stack); int result = calculate(operand1, operand2, expression[++i]); push(&stack, result); } i++; } return pop(&stack); } int main() { char expression[] = "3.5.2.-*7.+@"; int result = evaluatePostfixExpression(expression); printf("Result: %d\n", result); return 0; } ``` 这段代码实现了一个后缀表达式的计算器,可以计算给定后缀表达式的结果。在示例代码中,后缀表达式"3.5.2.-*7.+"被转换为中缀表达式"3*(5-2)+7",最终计算结果为16。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值