• B


    B - Investigating Div-Sum Property

    UVA - 11361

    题目描述:

    例题6 数字和与倍数

    ​ 给定正整数a,b,k 你的任务是在所有满足a<=n<=b的整数n中,统计有多少个满足n自身是k的倍数,且n的各个数字(十进制)之和也是k的倍数?比如当k=7时,322满足条件,因为322和3+2+2都是7的整数倍。当a=1,b=1000,k=4时,有64个整数条件。

    输入格式:

    输入第一行为测试数据组数T(T<100)。以下T行每行3个整数a,b,k(1<=a<=b<=231, 1<=k<=1000)

    输出格式:

    对于每组数据,输出满足条件整数的个数

    输入数据:

    3

    1 20 1

    1 20 2

    1 1000 4

    输出数据:

    20

    5

    64

    思路:

    不难想到用f(n)来表示 0~n中满足条件的个数,那么答案就是 f(b)f(a1)f(b)-f(a-1)

    可以用加法原理

    比如3212可以表示为

    0***

    1***

    2***

    30**

    31**

    320*

    3210

    3211

    3212

    ​ *代表该数字为0~9中的其中一个

    ​ 用 f(d,m1,m2)f(d,m1,m2)来表示d个数字,十进制数位之和取余k等于m1,值取余k等于m2。

    那么 $ f (d+1,m1,m2)=sum_{x=0}^{9} f ( d, (m1-x)%k,(m2-10^d)%k)$

    当然 f(3,0,0)就值0~999中满足条件的个数

    然后模拟将数字分解为上述情况,记下每种情况的前缀值和十进制位数的前缀和,计算出该情况下满足条件的个数就好了

    举个例子:

    0*** 用f(3,0,0)

    1*** 用f(3,-1+k%k,-1000%k)

    下面的就不列举了

    注意int行十进制位数之和最大位9*9+1=100 所以不可能被大于100的k取余,所以当k>100的时候只有0符合条件

    #include<cstdio>
    #include<algorithm>
    #include<stack>
    #include<queue>
    #include<cstring>
    #include<string>
    #include<iostream>
    #include<iomanip>
    #define mset(a,b)   memset(a,b,sizeof(a))
    using namespace std;
    typedef unsigned long long ull;
    typedef long long ll;
    const int maxn=10000;
    const int branch=26;
    const int inf=0x3f3f3f3f;
    const int MOD=1e6+7;
    int k;//取余k
    int f[12][105][105];
    int get_mod(int n,int mod);
    void init()
    {
        mset(f,0);//f[d][m1][m2]  要求 d>=1且 m1
        f[0][0][0]=1;//初始条件
        int ppw=1;
        for(int i=1;i<=9;++i)
        {
            for(int m1=0;m1<k;m1++)
            {
                for(int m2=0;m2<k;++m2)
                {
                    int sum=0;
                    for(int x=0;x<=9;++x)//枚举第i位数字
                    {
                        sum+=f[i-1][get_mod(m1-x,k)][get_mod(m2-x*ppw,k)];
                    }
                    f[i][m1][m2]=sum;
                }
            }
            //记录 10^(i-1)
            ppw*=10;
        }
    }
    int get_mod(int n,int mod)
    {
        return (n%mod+mod)%mod;
    }
    int solve(int num)//求0~num中有多少个数满足 取余k
    {
       if(num==0)
         return 1;
       int ans=0;
       int top=0,pos[10];
       int nn=num;
       while(nn)
       {
           pos[top++]=nn%10;
           nn/=10;
       }
       int sum=0;//记录前缀的值
       int ppw=1;//记录权值
       int ss=0;//记录前缀的市值仅为之和
       for(int i=0;i<top-1;++i)
        ppw*=10;
       for(int i=top-1;i>=0;--i)
       {
           for(int j=0;j<pos[i];++j)
           {
               ans+=f[i][get_mod(-1*ss-j,k)][get_mod(-1*sum-ppw*j,k)];//组合数学加法原理
           }
           sum+=ppw*pos[i];
           ss+=pos[i];
           ppw/=10;
       }
       ans+=f[0][get_mod(-ss,k)][get_mod(-sum,k)];
       return ans;
    }
    int main()
    {
        int t,a,b,ans;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d %d %d",&a,&b,&k);
            if(k>100)
            {
                printf("0
    ");
                continue;
            }
            init();//根据k 算出   0~9位数都有多少个
            ans=solve(b)-solve(a-1);
            printf("%d
    ",ans);
        }
        return 0;
    }
    
    
    
  • 相关阅读:
    C#多线程(16):手把手教你撸一个工作流
    C#多线程(15):任务基础③
    C#多线程(14):任务基础②
    C#多线程(13):任务基础①
    C#多线程(12):线程池
    C#多线程(11):线程等待
    C#多线程(10):读写锁
    C#多线程(9):多阶段并行线程
    C#多线程(8):线程完成数
    C#多线程(7):手动线程通知
  • 原文地址:https://www.cnblogs.com/dchnzlh/p/10427282.html
Copyright © 2020-2023  润新知