zoukankan      html  css  js  c++  java
  • scau 2012新生赛 G只有神知道的世界

    数论水题,但是因为自己数论比较弱,而且这题也想了半个小时,所以还放上来

    题意:

    对于任意一个非负数N,我们定义D(N) 为N上奇数数字的和加上两倍偶数数字的和。举个例子:D(567) = 5 + 6 * 2 + 7 = 24, D(314159) = 3 + 1 + 2 * 4 + 1 + 5 + 9 = 27.  
    令F(N)表示D(N)的最后一位数字。例如:F(567) = 4, F(314159) = 7。
    你的问题是,给你两个数A, B,你要计算出∑F(i), i ∈ [A, B]

    输入格式

    第一行输入一个整数T,表述有T组case。(T <=1000)
    接下来T行,每行输入两个数字A, B (0 <= A <= B <= 400,000,000)
    

     

    输出格式

    每一行输出一个整数,表示题目所要求的和。 

     

    输入样例

    3
    1 8
    28 138
    314159 314159
    

     

    输出样例

    36
    495
    7


    此题很明显的数论(数学题),数据很大,显然不可能用循环否则必定超时,只能发掘它的巧妙之处直接计算,这是数学题的特点,用对的算法,时间复杂度往往是O(1),不对的话,一般是TLE,还有可能WA
    这题首先想到了分治法统计在AB区间内所有数字出现过的次数,然后求和再求模,简单证明一下这个方法发现是错的,再用了几组数据发现也是错的,所以抛弃了这个方法。再想,会不会是有什么规律,但是一眼也看不出什么特别的规律,当时只知道一个规律,从0到9的Fn分别是0,1,4,3,8,5,2,7,6,9,也就是刚好0到9这10个数字又出现了一遍,和为45。然后再纸上老老实实列出了0到30的所有Fn,列到29的时候顿悟了。是存在一个周期,周期是10,在周期以外的数字单独处理,因为周期是10,所有周期以外的数字不会超过10个,最多9个,而周期以内的数字一个数学公式解决,时间复杂度可以说是几乎O(1)
    那么这个周期是什么?
    那就是从任意一个数字m开始,这个数字满足一个条件个位数是0,一直到m+9(那么显然m+9的个位数就是9),一共10个数字,这个10个数字的Fn之和为45
    这个东西的证明写起来有些麻烦就不写了,稍微思考一下谁都懂的
    所以给出区间[H,L],要保证H的个位数为0,L的个位数为9,如果不满足,则单独求H的Fn,并且让H递增知道H个位数等于0为止,同理若L个位数不为9,则单独求L的Fn,并让L递减直到个位数等于9为止
    预处理后[H,L]就是一个包含1个或多个周期的区间,求出区间长度并求出周期个数,每个周期的Fn和为45,
    则len=(L-H+1),c=len/10; s=c*45;
    ans=s+之前单独计算的H和L部分的Fn值

    然后注意处理一个特殊情况就是区间[H,L]的长度都不满足一个周期,也就是H递增和L递减之后区间已经全部单独计算完了,这时候就不用算什么周期了

    嗯,总的来说还是一道水题,现在还没有加强数论(数学)题的训练,以后要加强训练啊
    
    
    #include <cstdio>
    #include <cstring>
    char s[50];
    int H,L,ans;
    
    int get_dn(int n)
    {
        int sum=0,tmp;
        while(n>0)
        {
            tmp=n%10;
            if(tmp&1)  //奇数
                sum+=tmp;
            else
                sum+=tmp*2;
            n/=10;
        }
        return sum;
    }
    int get_fn(int n)
    {
        return get_dn(n)%10;
    }
    int main()
    {
        int T;
        scanf("%d",&T);
         while(T--)
         {
             scanf("%d%d",&H,&L);
             ans=0;
             while(H<=L)
             {
                 if((H%10)==0)  break; //个位是0
                 ans+=get_fn(H);
                 H++;
             }
             while(H<=L)
             {
                 if((L%10)==9)  break;
                 ans+=get_fn(L);
                 L--;
             }
             if(H>L)  //已经算完了
                printf("%d\n",ans);
             else
             {
                 ans+=(L-H+1)/10*45;
                 printf("%d\n",ans);
             }
         }
         return 0;
    }
  • 相关阅读:
    eclipse自动部署问题
    eclipse下遇到 无法解析类型 javax.servlet.http.HttpServletRequest
    Spring MVC学习笔记——POJO和DispatcherServlet
    JavaWeb学习笔记——Tomcat数据源
    JavaWeb学习笔记——表达式语言
    Bootstrap学习笔记
    ubuntu下git安装及使用
    JavaWeb学习笔记——jsp基础语法
    Java数据结构——容器总结
    Linux下htop的使用
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2798419.html
Copyright © 2011-2022 走看看