zoukankan      html  css  js  c++  java
  • Codeforce 55D Beautiful numbers

    Beautiful numbers

    题意:挑选出数字,这些数字能被他们的非0位整除。

    思路:数位DP,由于1~9的最大公倍数是2520, dp[][维护对2520的余数][已经统计到的余数],再对有可能用到的余数进行离散化。

    代码如下:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #define N 3000
    typedef long long ll;
    const int mod=2520LL;
    using namespace std;
    ll k,t,dp[20][N][60],ans,prime[N],dig[20],LCM[N][N];
    ll a,b;
    ll gcd(ll a,ll b)
    {
    	return b==0?a:gcd(b,a%b);	
    }
    
    ll dfs(ll pos,ll num,ll lcm,ll lim)
    {
    	if(pos<0) return num%lcm==0;
    	if(dp[pos][num][prime[lcm]]!=-1&&!lim) return dp[pos][num][prime[lcm]];
    	ll cnt=0;
    	ll r=lim?dig[pos]:9;
    	for(int l=0;l<=r;l++){
    		ll nenum=(num*10+l)%mod;
    		ll nelcm=l?LCM[lcm][l]:lcm;
    		cnt+=dfs(pos-1,nenum,nelcm,lim&&(l==r));
    	}
    	if(!lim) dp[pos][num][prime[lcm]]=cnt;
    	return cnt;
    
    }
    void init()
    {
    	ll tmp=0;
    	for(ll i=1;i<=mod;i++)
    	{
    		if(mod%i==0){
    			prime[i]=tmp++;
    		}
    	}
    	for(ll i=1;i<=mod;i++)
    		for(ll j=1;j<10;j++){
    			LCM[i][j]=i*j/gcd(i,j);
    		}
    }
    ll solve(ll a)
    {
    	ll ti=0;
    	while(a)
    	{
    		dig[ti++]=a%10;
    		a/=10;
    	}
    	return dfs(ti-1,0,1,1);
    }
    int main()
    {
    	init();
    	scanf("%lld",&t);
    	memset(dp,-1,sizeof(dp));
    	while(t--){
    		scanf("%lld%lld",&a,&b);
    		printf("%lld
    ",solve(b)-solve(a-1));
    	}
    	return 0;
    }
    
  • 相关阅读:
    LintCode "Maximum Gap"
    LintCode "Wood Cut"
    LintCode "Expression Evaluation"
    LintCode "Find Peak Element II"
    LintCode "Remove Node in Binary Search Tree"
    LintCode "Delete Digits"
    LintCode "Binary Representation"
    LeetCode "Game of Life"
    LintCode "Coins in a Line"
    LintCode "Word Break"
  • 原文地址:https://www.cnblogs.com/Crazycatmiao/p/6897145.html
Copyright © 2011-2022 走看看