zoukankan      html  css  js  c++  java
  • 【思维+大数(高精度)】number 计蒜客 45276

    题目:

    求 1 到 10^n 的数字中有 3 的数字的数量。

    输入格式

    1 个整数 n

    输出格式

    共一行,1 个整数,表示答案。

    数据范围

    对于 10% 的数据,n8

    对于 30% 的数据,n18

    对于 100% 的数据,n1000

    Sample Input

    2

    Sample Output

    19

    题解:

    当n=1000时,1e1000内有部分是3e999,这里有1e999个含有数字3的数字,所以很明显该题是大数运算或者是规律题。

    进行简单的模拟,

    n=1,有ans=1;即10之内只有3;

    n=2,有ans=19;即100之内有03,13,23...93,10个与30,31...39,10个,同时因为33是两类的交集,所以要去掉重复的一个;

    n=3,有ans=271;1000之内有10个x00~x99, 同时有300~399,(x表示任意数字),即有10个ans2和100,再去除重复的3xx里面的19个重复

    所以ans3=ans2*10+100-ans2

    n=4,有ans=3439;同理可得ans4=ans3*9+1e(n-1);

    所以可归纳出ansn=ans(n-1)*9+1e(n-1);(n>=2)

           ans1=1;

    根据该公式可判断出输出并未又整齐固定的规律,所以该题是大数运算。

    根据公式可以判断需要用到大数加分和大数乘法。

    大数运算其实就是通过数组模拟的数学运算,数组的每一数值表示是一个10进制的位,大数加法就是把每位数字相加并进位,大数乘法就是模拟小学学的那种运算方法,将一个乘数的每一个位乘另一个乘数,并求和。

    AC代码:

    #include<iostream>
    #include<cstring>
    #define max(a,b){(((a)>(b))?(a):(b))}
    #define claer(x){memset(x,0,sizeof(x));}
    using namespace std;
    
    int ans[1005];
    int tmp1[1005];int _9[5];
    int _10[1005];
    
    int add(int *a, int alen, int *b, int blen) {
        int len = max(alen, blen);
        for (int i = 0; i < len; i++) {
            a[i] += b[i];
            a[i + 1] += a[i] / 10;
            a[i] %= 10;
        }
        len++;
        while (a[len]==0)len--;
        return len+1;
    }
    
    int mul(int *a, int alen, int *b, int blen) {
        claer(tmp1);
        int t2len = 0;
        for (int i = 0; i < blen; i++) {
            for (int j = 0; j < alen; j++) {
                tmp1[i + j] += b[i] * a[j];
                tmp1[i + j + 1] += tmp1[i + j] / 10;
                tmp1[i + j] %= 10;
            }
            
        }
        int n = alen + blen+5;
        while (tmp1[n]==0)n--;
        for (int i = 0; i <= n; i++)
            a[i] = tmp1[i];
        return n+1;
    }
    
    
    int main() {
    #if 0
        //freopen("number.in", "r", stdin);
        //freopen("number.out", "w", stdout);
    #endif
        int n, len = 1;
        cin >> n;
        ans[0] = 1;
        _9[0] = 9;
        for (int i = 1; i < n; i++) {
            len = mul(ans, len, _9, 1);
    
            _10[i] = 1;
            _10[i - 1] = 0;
    
            len = add(ans, len, _10, i + 1);
        }
    
        for (int i = len - 1; i >= 0; i--) {
            printf("%d", ans[i]);
        }
    
    
    }

  • 相关阅读:
    Java Swing打猎射击游戏源码
    php实现在线下载程序安装包功能
    WP
    双人对战的球类游戏IOS源码
    非常不错的新闻客户端应用安卓源码
    创业建议:如何写挖人邮件
    wp8路线跟踪应用源码详细说明
    wp版笔记本应用源码
    旅游风景展示应用源码iPad版
    bitset优化背包
  • 原文地址:https://www.cnblogs.com/komet/p/12936036.html
Copyright © 2011-2022 走看看