Codeforces-55D Beautiful numbers

http://codeforces.com/problemset/problem/55/D

Volodya is an odd boy and his taste is strange as well. It seems to him that a positive integer number is beautiful if and only if it is divisible by each of its nonzero digits. We will not argue with this and just count the quantity of beautiful numbers in given ranges.

Input

The first line of the input contains the number of cases t (1 ≤ t ≤ 10). Each of the next t lines contains two natural numbers li and ri (1 ≤ li ≤ ri ≤ 9 ·1018).

Please, do not use %lld specificator to read or write 64-bit integers in C++. It is preffered to use cin (also you may use %I64d).

Output

Output should contain t numbers — answers to the queries, one number per line — quantities of beautiful numbers in given intervals (from li to ri, inclusively).

 

题意:求区间美丽数的个数。所谓美丽数,是指一个数可以被它的每一位数字整除。

思路:因为num可以被它的每一位整除,等价于num可以被其每一位的lcm整除。

但是,状态不能设为(第pos位,以前每位的lcm),举个例子,num1=32,num2=312,假如按刚刚的状态跑到最后'2'那一位时,当前lcm都是3,但是312%6==0,而32%6!=0。

即算是不是美丽数,必须由整个num%lcm(每一位)。

由于x%b==x%(k*b)%b,lcm(1~9)=2520,num%lcm=num%2520%lcm

状态设为(第pos位,以前数%2520的值,当前lcm)

但是这个状态有18*2525*2520,空间开不下,因为1~9任意组合的lcm是离散的,只有48种组合,最后一维可以离散化一下。

参考这篇https://blog.csdn.net/qq_33184171/article/details/52332586

#include<bits/stdc++.h>
using namespace std;
#define ll unsigned long long

ll T,A,B;
ll a[20],dp[20][2600][50];
ll lcm_id[2530];

ll Lcm(ll a,ll b)
{
	if(!b)return a;
	return a/__gcd(a,b)*b;
}

ll dfs(ll pos,ll mod,ll lcm,bool limit)
{
	if(pos==-1)return mod%lcm==0;
	if(!limit&&dp[pos][mod][lcm_id[lcm]]!=-1)return dp[pos][mod][lcm_id[lcm]];
	int up= (limit?a[pos]:9);
	ll ans=0;
	for(int i=0;i<=up;i++)
	{
		ans+=dfs(pos-1,(mod*10+i)%2520,Lcm(lcm,i),limit&&i==a[pos]);
	}
	if(!limit)dp[pos][mod][lcm_id[lcm]]=ans;
	return ans;
}

ll solve(ll n)
{
	int pos=0;
	while(n)
	{
		a[pos++]=n%10;
		n/=10;
	}
	return dfs(pos-1,0,1,1);
}

void init()
{
	int idx=0;
	bool vis[2530]={0};
	for(int i=1;i<(1<<9);i++)
	{
		int ret=1;
		for(int j=0;j<9;j++)if((1<<j)&i)ret=Lcm(ret,j+1);
		if(!vis[ret])
		{
			vis[ret]=1;
			lcm_id[ret]=++idx;
		}
	}
}

int main()
{
//	freopen("input.in","r",stdin);
	memset(dp,-1,sizeof(dp));
	init();
	cin>>T;
	while(T--)
	{
		cin>>A>>B;
		cout<<solve(B)-solve(A-1)<<endl;
	}
	return 0;
} 

 

全部评论

相关推荐

昨天 18:48
重庆大学 C++
点赞 评论 收藏
分享
会飞的猿:我看你想进大厂,我给你总结一下学习路线吧,java语言方面常规八股要熟,那些java的集合,重点背hashmap八股吧,jvm类加载机制,运行时分区,垃圾回收算法,垃圾回收器CMS、G1这些,各种乐观锁悲观锁,线程安全,threadlocal这些。在进阶一些的比如jvm参数,内存溢出泄漏排查,jvm调优。我这里说的只是冰山一角,详细八股可以去网上找,这不用去买,都免费资源。mysql、redis可以去看小林coding,我看你简历上写了,你一定要熟,什么底层b+树、索引结构、innodb、mvcc、undo log、redo log、行级锁表级锁,这些东西高频出现,如果面试官问我这些我都能笑出来。消息队列rabbitmq也好kafka也好,学一种就行,什么分区啊副本啊确认机制啊怎么保证不重复消费、怎么保证消息不丢失这些基本的一定要会,进阶一点的比如LEO、高水位线、kafka和rocketmq底层零拷贝的区别等等。计算机网络和操作系统既然你是科班应该理解起来问题不大,去看小林coding这两块吧,深度够了。spring boot的八股好好看看吧,一般字节腾讯不这么问,其他的java大厂挺爱问的,什么循环依赖啥的去网上看看。数据结构的话科班应该问题不大,多去力扣集中突击刷题吧。项目的话其实说白了还是结合八股来,想一想你写的这些技术会给你挖什么坑。除此之外,还有场景题、rpc、设计模式、linux命令、ddd等。不会的就别往简历上写了,虽然技术栈很多的话好看些,但背起来确实累。总结一下,多去实习吧,多跳槽,直到跳到一个不错的中厂做跳板,这是一条可行的进大厂的路线。另外,只想找个小厂的工作的话,没必要全都照这些准备,太累了,重点放在框架的使用和一些基础八股吧。大致路线就这样,没啥太多难度,就是量大,你能达到什么高度取决于你对自己多狠,祝好。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务