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;
    }
    
  • 相关阅读:
    noi.ac NOI挑战营模拟赛1-5
    TJOI2015 弦论
    CQOI2018 破解D-H协议
    NOI2013 矩阵游戏
    NOI2015 荷马史诗
    NOI2015 寿司晚宴
    SDOI2014 重建
    NOI1999 生日蛋糕
    NOI2015 程序自动分析
    ZJOI2008 泡泡堂
  • 原文地址:https://www.cnblogs.com/Crazycatmiao/p/6897145.html
Copyright © 2011-2022 走看看