zoukankan      html  css  js  c++  java
  • P2602 [ZJOI2010]数字计数&P1239 计数器&P4999 烦人的数学作业

    P2602 [ZJOI2010]数字计数

    题解

    DFS 恶心的数位DP

    对于这道题,我们可以一个数字一个数字的求

    也就是分别统计区间 [ L , R ] 内部数字 i 出现的次数 (0<=i<=9)

    也就是DFS只需要记录 :

    当前填到第几位 pos

    k一共出现多少次 sum

    目标数字 k

    是否顶上界 limit

    是否全是前导零 qdl

    dp[pos][sum]:

    >不顶上界,没有前导零,

      当前填到第pos位,目标数字一共出现sum次的时候(前pos位中一共有sum个目标数字)

      对答案产生的贡献

    >由于sum最多会取到和pos一样的个数,所以数组大小开的和pos一样就好了

    这里 sum 记录的时候分两种情况:

    (1)k!=0     直接看看 所填数字是否目标数字 就好了

    (2)k=0      <1> 前面全是前导零,但是所填数字不是0

                         <2> 填到最后数字是0,也就是0000000,此时0要算出现一次

                         <3> 其余情况就不记录0出现的次数了

    代码

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    
    using namespace std;
    
    typedef long long ll;
    
    inline ll read()
    {
        ll ans=0;
        char last=' ',ch=getchar();
        while(ch<'0'||ch>'9') last=ch,ch=getchar();
        while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar();
        if(last=='-') ans=-ans;
        return ans;
    }
    
    ll a,b;
    ll c[20],len;
    ll dp[20][20];
    
    ll dfs(ll pos,ll sum,ll k,bool limit,bool qdl)
    {
        if(pos<=0) return sum;
        if(!limit&&!qdl&&dp[pos][sum]!=-1) return dp[pos][sum];
        ll ans=0;
        ll up=limit?c[pos]:9;
        for(int i=0;i<=up;i++)
            ans+=dfs(pos-1,sum+(k==0?(!qdl&&i==0)||(qdl&&i==0&&pos==0):(i==k)),k,limit&&(i==up),qdl&&(i==0));
        if(!limit&&!qdl) dp[pos][sum]=ans;
        return ans;
    }
    
    ll sum(ll x,ll k)
    {
        memset(c,0,sizeof(c));len=0;
        memset(dp,-1,sizeof(dp));
        while(x)
        {
            c[++len]=x%10;
            x/=10;
        }
        return dfs(len,0,k,1,1);
    }
    
    int main()
    {
        a=read();b=read();
        for(int i=0;i<=9;i++)
          printf("%lld ",sum(b,i)-sum(a-1,i));
        
        return 0;
    }

    双倍经验(比第一个简单)

    P1239 计数器

    题解

    也就是只需要一个 a 就够够的了

    代码

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    
    using namespace std;
    
    typedef long long ll;
    
    inline ll read()
    {
        ll ans=0;
        char last=' ',ch=getchar();
        while(ch<'0'||ch>'9') last=ch,ch=getchar();
        while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar();
        if(last=='-') ans=-ans;
        return ans;
    }
    
    const ll mod=1e9+7;
    ll a,b,T,ans=0;
    ll c[30],len;
    ll dp[30][30];
    
    ll dfs(ll pos,ll sum,ll k,bool limit,bool qdl)
    {
        if(pos<=0) return sum;
        if(!limit&&!qdl&&dp[pos][sum]!=-1) return dp[pos][sum];
        ll ans=0;
        ll up=limit?c[pos]:9;
        for(int i=0;i<=up;i++)
            ans+=dfs(pos-1,sum+(k==0?(!qdl&&i==0)||(qdl&&i==0&&pos==0):(i==k)),k,limit&&(i==up),qdl&&(i==0));
        if(!limit&&!qdl) dp[pos][sum]=ans;
        return ans;
    }
    
    ll sum(ll x,ll k)
    {
        memset(c,0,sizeof(c));len=0;
        memset(dp,-1,sizeof(dp));
        while(x)
        {
            c[++len]=x%10;
            x/=10;
        }
        return dfs(len,0,k,1,1);
    }
    
    int main()
    {
        a=read();
        for(int i=0;i<=9;i++)
           printf("%lld
    ",sum(a,i));    
        return 0;
    }

    三倍经验

    P4999 烦人的数学作业

    题解

    拿题一看:我要AC辣!!!

    现实是 90pt

    为哈!!!!!!

    取模的锅,多取几次

    我还是太天真

    代码

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    
    using namespace std;
    
    typedef long long ll;
    
    inline ll read()
    {
        ll ans=0;
        char last=' ',ch=getchar();
        while(ch<'0'||ch>'9') last=ch,ch=getchar();
        while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar();
        if(last=='-') ans=-ans;
        return ans;
    }
    
    const ll mod=1e9+7;
    ll a,b,T,ans=0;
    ll c[20],len;
    ll dp[20][20];
    
    ll dfs(ll pos,ll sum,ll k,bool limit,bool qdl)
    {
        if(pos<=0) return sum;
        if(!limit&&!qdl&&dp[pos][sum]!=-1) return dp[pos][sum];
        ll ans=0;
        ll up=limit?c[pos]:9;
        for(int i=0;i<=up;i++)
            ans+=dfs(pos-1,sum+(k==0?(!qdl&&i==0)||(qdl&&i==0&&pos==0):(i==k)),k,limit&&(i==up),qdl&&(i==0));
        if(!limit&&!qdl) dp[pos][sum]=ans;
        return ans;
    }
    
    ll sum(ll x,ll k)
    {
        memset(c,0,sizeof(c));len=0;
        memset(dp,-1,sizeof(dp));
        while(x)
        {
            c[++len]=x%10;
            x/=10;
        }
        return dfs(len,0,k,1,1);
    }
    
    int main()
    {
        T=read();
        while(T--)
        {
            ans=0;
            a=read();b=read();
            for(int i=1;i<=9;i++)
            {
                ll tmp=((sum(b,i)-sum(a-1,i))%mod+mod)%mod; 

    a
    ns=((ans+i*tmp%mod+mod)%mod+mod)%mod; } printf("%lld ",ans%mod); } return 0; }
  • 相关阅读:
    mysql中文乱码的一点理解
    Linux 运行进程实时监控pidstat命令
    深入理解“系统平均负载”
    进程和线程的区别
    vmstat命令
    grep命令
    top命令
    Shell脚本获取本机ip
    CentOS7防火墙(firewall)配置
    大数据测试
  • 原文地址:https://www.cnblogs.com/xiaoyezi-wink/p/11482412.html
Copyright © 2011-2022 走看看