计算n!的位数<Math>

题意:如题目.

方法一:<TLE>
 *    可设想n!的结果是不大于10的M次幂的数,即n!<=10^M(10的M次方),则不小于M的最小整数就是 n!的位数,对
 *    该式两边取对数,有 M =log10^n! 即:M = log10^1+log10^2+log10^3...+log10^n 循环求和,就能算得M值,
 *    该M是n!的精确位数。当n比较大的时候,这种方法方法需要花费很多的时间。
 *
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int main ()
{
    int n;
    double sum;
    while(scanf("%d",&n)!=EOF)
    {
        sum=1;
        for(int i=2;i<=n;i++)
            sum+=log10(i);
        printf("%d\n",(int)sum);
    }
    return 0;
}

*    方法二:
 *    利用斯特林(Stirling)公式的进行求解。下面是推导得到的公式:
 *    res=(long)( (log10(sqrt(4.0*acos(0.0)*n)) + n*(log10(n)-log10(exp(1.0)))) + 1 );
 *    当n=1的时候,上面的公式不适用,所以要单独处理n=1的情况!

#include<cstdio>

#include<cstdlib>

#include<cstring>

#include<string>

#include<algorithm>

#include<cmath>

#include<vector>

#include<stack>

#include<map>

#include<queue>

#include<iostream>

using namespace std;

typedef long long ll;

int main ()

{

    ll n;

    double ans;

    while(~scanf("%lld",&n))

    {

        ans=1;

        if(n!=1&&n!=0)

            ans=double( (log10(sqrt(4.0*acos(0.0)*n)) + n*(log10(n)-log10(exp(1.0))))+1);

         // ans=floor ((log(sqrt(2*n*pi))+n*log((double)n)-n)/log(10.0))+1;

        printf("%lld\n",(ll)ans);

    }

    return 0;

}

//exp(x) #include<cmath>:求e^x.


你的代码目的是处理多个查询,每个查询给出一个位置k,要求找出无限数字字符串中第k位的数字。然而,当前代码存在一些问题,导致无法正确输出结果。以下是代码的问题分析和修正建议: ### 问题分析 1. **逻辑错误**: - 在计算`num`时,你的公式`(a[i] - 1) / n`是正确的,但后续的`if (a[i] <= 9) num = a[i] / n`是多余的,并且会导致错误。例如,当`a[i] = 3`时,`num`会被错误地计算为`3 / 1 = 3`,而实际上应该是`(3 - 1) / 1 = 2`(即数字`2`的某一位)。 - 你没有将`start`加到`num`上,导致`num`是从0开始计算的,而不是从`start`开始。 2. **输出错误**: - 你直接输出了`num`,但题目要求输出的是第k位的数字,而不是数字本身。你需要将`num`转换为字符串,然后取出对应的位。 3. **变量命名和初始化**: - `cnt`和`start`的初始化是正确的,但`n`的初始值为1是正确的。 - 你在循环中修改了`a[i]`的值,这可能会引起混淆,建议使用一个临时变量来处理。 ### 修正后的代码 以下是修正后的代码,解决了上述问题: ```cpp #include <iostream> #include <string> using namespace std; char findKthDigit(int k) { int n = 1; // 数字的位数 long long count = 9; // n位数的数字共有count个 long long start = 1; // n位数的起始数字 while (k > n * count) { k -= n * count; n++; count *= 10; start *= 10; } // 找到具体的数字 long long num = start + (k - 1) / n; // 找到数字中的具体位 int digit_pos = (k - 1) % n; return to_string(num)[digit_pos]; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int q; cin >> q; while (q--) { int k; cin >> k; cout << findKthDigit(k) << '\n'; } return 0; } ``` ### 修正点说明 1. **`findKthDigit`函数**: - 正确计算数字的位数`n`、数字的个数`count`和起始数字`start`。 - 通过循环减去前面所有位数较少的数字贡献的总位数,直到找到`k`所在的位数范围。 - 计算具体的数字`num`:`start + (k - 1) / n`。 - 计算数字中的具体位:`(k - 1) % n`,并返回该位的字符。 2. **主函数**: - 使用`ios::sync_with_stdio(false)`和`cin.tie(nullptr)`来加速输入。 - 读取查询数量`q`,然后处理每个查询,调用`findKthDigit`并输出结果。 ### 示例测试 输入: ``` 3 3 11 15 ``` 输出: ``` 3 0 2 ``` 解释: - 第3位是`3`(字符串`123...`的第3位)。 - 第11位是`0`(字符串`12345678910...`的第11位是`10`中的`0`)。 - 第15位是`2`(字符串`123456789101112...`的第15位是`12`中的`2`)。 ### 总结 修正后的代码能够正确处理查询,并高效地找到无限数字字符串中第k位的数字。关键在于正确计算数字的位数和具体位置,并将数字转换为字符串以提取对应的位。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值