首页 > 其他分享 >P2567 [SCOI2010] 幸运数字

P2567 [SCOI2010] 幸运数字

时间:2023-07-22 14:45:13浏览次数:62  
标签:tmp lcm return int len 幸运 SCOI2010 P2567

题目链接

题目中询问数据范围达到了1e10,且要求找符合要求数的个数,很容易让我想到数位dp,但其实每必要,发现幸运数字只有 \(2^{10}\) 个,答案就是近似幸运数+幸运数-两者交集,考虑容斥,每个 \([l,r]\) 之间的可能被之前的幸运数更新多次,通过容斥,很容易知道1个幸运数个数-2个幸运数lcm个数+3个幸运数lcm个数...dfs实现,但显然会T,考虑优化,一个幸运数是之前的幸运数倍数,就没必要对他dfs了;还有,因为lcm>qr时就可以退出了,所以我们的数越大,lcm增加的就越快,dfs递归次数就会越少(最好卡常会更快)

计算 \([l,r]\) 间 \(X\) 倍数的个数,就是 \(floor(R/x)-ceil(L/x)+1\) 个

#include<bits/stdc++.h>
#define int __int128
using namespace std;
const int N=2e6+5;
int ql,qr,S1[N],cnt=0;
vector<int> E;
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)
    +fread(buf,1,100000, stdin),p1==p2)?EOF:*p1++;
}
template<typename T>inline
void read(T& x){
    T f=1,b=0;char ch=gc();
    while (ch<'0'||ch>'9') {
        if(ch=='-')f=-1;
        ch=gc();
    }
	while(ch>='0'&&ch<='9')
		b*=10,b+=ch-'0',ch=gc();
    x=f*b;return;
}
template<typename T> inline
void print(T x){
    if(x==0)return putchar('0'),void();
    if(x<0)putchar('-'),x=-x;
    int st[129]={0},k=0;
    while(x)st[++k]=x%10,x/=10;
    for(int i=k;i;i--)putchar(st[i]+'0');
} 
void dfs(int len,int x){
	if(x<=qr&&x){
		E.emplace_back(x);
	}
	if(x>qr)return;
	dfs(len+1,x*10+8);
	dfs(len+1,x*10+6);
	return;
} 
bool vis[N];
int gcd(int a,int b){
	return b?gcd(b,a%b):a;
}
int lcm(int a,int b){
	return a/gcd(a,b)*b;
}
int ans=0;
void dfs2(int len,int tmp,int sign){
	if(tmp>qr)return;
	if(len==cnt+1){
		if(!tmp)return;
		int tot=floor(qr*1.0/tmp)-ceil(ql*1.0/tmp)+1;
		ans=ans+sign*tot;
		return;
	}
	int ntmp;
	if(!tmp)ntmp=S1[len];
	else ntmp=lcm(tmp,S1[len]);
	dfs2(len+1,ntmp,-sign);
	dfs2(len+1,tmp,sign); 
	return;
}
bool cmp(int a,int b){
	return a>b;
}
signed main(){
	read(ql),read(qr);
	dfs(0,0);
	sort(E.begin(),E.end());
	for(int i=0;i<E.size();i++){
		if(vis[i])continue;
		S1[++cnt]=E[i];
		for(int j=i+1;j<E.size();j++){
			if(E[j]%E[i]==0)vis[j]=true; 
		}
	}
	sort(S1+1,S1+cnt+1,cmp); 
	dfs2(1,0,-1);
	print(ans),puts("");
	return 0;
}

标签:tmp,lcm,return,int,len,幸运,SCOI2010,P2567
From: https://www.cnblogs.com/blueparrot/p/17573340.html

相关文章

  • 【2023.05.04】幸运的猫(下)
    本次博客主要写黑猫回家后的故事未到家前我打电话和我父亲开玩笑说要带女朋友回家过年我爹还蛮激动的,问是哪里的女孩子,我说是福州的忘记了带回家后他是什么心情了哈哈果然还是要多写日记啊,不然什么都忘记了可太糟糕了初到家中初到家里的时候是还关在笼子里的,因为想把猫养......
  • NC20279 [SCOI2010]序列操作
    题目链接题目题目描述lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作:0ab把[a,b]区间内的所有数全变成01ab把[a,b]区间内的所有数全变成12ab把[a,b]区间内的所有数全部取反,也就是说把所有的0变成1,......
  • L1-062 幸运彩票
    题目:彩票的号码有6位数字,若一张彩票的前3位上的数之和等于后3位上的数之和,则称这张彩票是幸运的。本题就请你判断给定的彩票是不是幸运的。输入格式:输入在第一行中给出一个正整数N(≤ 100)。随后N行,每行给出一张彩票的6位数字。输出格式:对每张彩票,如果它是幸运的,就在一行......
  • 【2023.04.21】幸运的猫(上)
    此文用来记录我家黑猫旺来出生和黑猫的初见是在19年的9月份,那时的我暑假留校后,给自己留了两周的假期回家这个暑假我周游了整个福大,拍了可能有二三十只流浪猫吧,认识了学校的所有流浪猫但是这只黑猫反而是我返校第一次见,开学后学校人多,加上我事情比较多,因此只匆匆拍了几张照片......
  • sdutoj3009 幸运数
    幸运数TimeLimit:1000ms  Memorylimit:262144K  有疑问?点这里^_^题目描述如果,a是幸运数,b是幸运数,那么a+b+2也是幸运数。现在,告诉你两个幸运数a和b,请问c是不是幸运数。输入输入数据有多行组成,首先是一个整数N(0<N<1000),表示测试实列的个数,然后是N行数据,每行......
  • 洛谷 P3292 [SCOI2016]幸运数字
    https://www.luogu.com.cn/problem/P3292多次询问求一条链取若干点的最大异或和考虑一个集合的最大异或和可以求出线性基完成,两个集合的线性基可以合并,但是线性基并没有可减性,于是我们求lca的时候只能每次往集合里添加一条链,为了保证复杂度只能用倍增做。std::vector<i64>......
  • 蓝桥杯备战日志(Python)18-第几个幸运数字-(枚举只含某些因子的整数)
    第几个幸运数字原题到X星球旅行的游客都被发给一个整数,作为游客编号。X星的国王有个怪癖,他只喜欢数字3,5和7。国王规定,游客的编号如果只含有因子:3,5,7就可以获得一......
  • 最幸运的数字
    最幸运的数字$8$是中国的幸运数字,如果一个数字的每一位都由$8$构成则该数字被称作是幸运数字。现在给定一个正整数$L$,请问至少多少个$8$连在一起组成的正整数(即最......
  • 幸运数
    幸运数是波兰数学家乌拉姆命名的。它采用与生成素数类似的“筛法”生成。首先从1开始写出自然数1,2,3,4,5,6,....1就是第一个幸运数。我们从2这个数开始。把所有序号能......
  • #ACM2021_23. 摘柿子 and#ACM2021_34. 幸运数字
    #ACM2021_23.摘柿子:一道很简单的排序题,估计是送分题(俺的做法:#include<stdio.h>#include<stdlib.h>#defineN100#defineM100intmain(){intn;//n为柿子个......