zoukankan      html  css  js  c++  java
  • 数字游戏(二)

                            数字游戏(二)

    题目描述

    由于科协里最近真的很流行数字游戏,某人又命名了一种取模数,这种数字必须满足各位数字之和mod N为0。现在大家又要玩游戏了,指定一个整数闭区间[a,b],问这个区间内有多少个取模数。 输入 题目有多组测试数据。每组只含三个数字a,b,N。

    输出

    对于每个测试数据输出一行,表示各位数字和mod N为0的数的个数。

    样例输入

    1 19 9

    样例输出

    2

    对于全部数据,1<=a,b<=2^31-1,1<=N<100。

    解析:

    STEP1:判断算法   

    根据数据范围,a,b<=1^31-1,也就是在int范围内,同时这使我们确定了用常规方法(暴力)没有办法AC,毕竟O(n)的算法都会TLE, 所以

    可以肯定这是一道在数位上做文章的题,也就是数位dp

       

     STEP2:找到状态    

    由于上一步已经知道这是一道数位dp,所以便可以很轻易的得知一定有一个维度属于数位,那我们思考一下,还有没有其他要记录的的呢?    

    很明显还有%n余几,所以dp[i][j]表示位数<=i的所有数中%n余j的数的个数。

    STEP3:状态转移

    一个数在末尾加一个k,这样dp(位数+1)((k+原来%n)%n),可以稍微展示一下我的dp方程

    for(int i=2;i<=q;i++)
    {
         for(int j=0;j<n;j++)
         {
              for(int k=0;k<=9;k++)
              {
                    dp[i][j]+=dp[i-1][(j-k+n*10)%n];
              }
         }
    }

    但是dp方程虽然求出来了,但还有一个很大的问题,就是它的左右端点不一定完美的是一个位数的左右端点,所以还得再处理一下

    STEP4:solve处理

    l到r之间的所有取模数可以看做1到r之间的所有取模数与1到l-1之间的所有取模数之差,所以solve(x)就只用计算1-x之间的取模数

    最后,solve有三个参数,分别是x,y,w,x是这个数,y是%n的值,而w是x的位数

    对于每个x,可以将它的最高位剥掉,然后将它加上对应的值,不断循环此过程,最后就出来答案了

    注意事项

    1.这题是多组数据!!!

    2.记得初始化!!!

    3.int再判断位数的时候会炸,要开long long!!!

    4.l有可能是0,所以最后要加上1!!!

    最后代码上来:

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    int xx1=1,xx2=1,p,q;
    int dp[105][205];
    int ans;
    int l,r,n;
    int zgw(int x)
    {
        int ans_=1;
        for(int i=1;i<=x-1;i++)
        {
            ans_*=10;
        }
        return ans_;
    }
    int sovle(int x,int y,int w)
    {
        int ans2=0;
        int s=9;
        int ss=1;
        while(x>s && w==-1)
        {
            s=s*10+9;
            ss++;
        }
        if(w!=-1) ss=w;
        if(ss==1)
        {
            y=y%n;
            if(x<y) return 0;
            return (x-y)/n+1;
        }
        for(int i=0;i<=x/zgw(ss)-1;i++)
        {
            ans2+=dp[ss-1][(11*n-i+y)%n];
        }
        return ans2+sovle(x%zgw(ss),(11*n-x/zgw(ss)+y)%n,ss-1);
    }
    signed main()
    {
        while(scanf("%lld%lld%lld",&l,&r,&n)!=EOF)
        {
            memset(dp,0,sizeof(dp));
            xx1=1,xx2=1;
            ans=0;
            if(!l) l++;
            for(int i=1;i<=15;i++)
            {
                if(xx1>l/10)
                {
                    p=i;
                    break;
                }
                xx1*=10;
            }
            for(int i=1;i<=15;i++)
            {
                if(xx2>r/10)
                {
                    q=i;
                    break;
                }
                xx2*=10;
            }
            q-=1;
            for(int i=0;i<=9;i++) dp[1][i%n]++;
            for(int i=2;i<=q;i++)
            {
                for(int j=0;j<n;j++)
                {
                    for(int k=0;k<=9;k++)
                    {
                        dp[i][j]+=dp[i-1][(j-k+n*10)%n];
                    }
                }
            }
            if(l==0) printf("%lld
    ",sovle(r,0,-1)-sovle(l-1,0,-1)+1);
            else printf("%lld
    ",sovle(r,0,-1)-sovle(l-1,0,-1));
        }
        return 0;
    }
    

      

  • 相关阅读:
    歌曲汇总
    赤道附近
    看樱花(也有很多其他花)
    线程池异常处理之重启线程处理任务
    ElasticSearch Index操作源码分析
    探究ElasticSearch中的线程池实现
    由字典树想到的
    ElasticSearch 启动时加载 Analyzer 源码分析
    Elasticsearch6.3.2启动过程源码阅读记录
    Elasticsearch High Level Rest Client 发起请求的过程分析
  • 原文地址:https://www.cnblogs.com/chen-1/p/11351866.html
Copyright © 2011-2022 走看看