#容斥,广搜#nssl 1458 HR的疑惑 nssl 1460 逛机房

nssl 1458 HR的疑惑

题目

\([1\sim n]\)中有多少个正整数\(x\)满足

\[\sqrt[y]{x}\in N^{+},y>1 \]

其中\(n\leq 10^{18}\)


分析

枚举指数,想要不重复必然是质数或互不相同的质数之积,
容斥求方案数,对于一个指数\(x\),不考虑重复的答案为\(\lfloor\sqrt[x]{n}\rfloor\)
注意特判1,将1每次统计时都减掉,最后再加上1


代码

#include <cstdio>
#include <cmath>
#include <algorithm>
#define rr register
using namespace std;
typedef long long lll; lll n; int xo[66011],sum,ans;
const int prime[17]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59};
signed main(){
	scanf("%lld",&n),xo[0]=0;
	for (rr int i=1;i<65536;++i) xo[i]=xo[i&(i-1)]+1;
	for (rr int i=0;i<17;++i){
		rr int now=pow(n,1.0/prime[i]),sum=now-1;
		if (now<2) break;
		for (rr int j=1;j<(1<<i);++j){
			rr int G=1,flag=1;
			for (rr int k=0;k<i;++k)
			if ((j>>k)&1){
				if (G>now/prime[k]) {flag=0; break;}
				G*=prime[k];
			}
			if (!flag) continue;
			rr int t=pow(now,1.0/G)-1;
			if (t<1) continue;
			sum+=(xo[j]&1)?-t:t;
		}
		ans+=sum;
	}
	return !printf("%d",ans+1);
}

nssl 1460 逛机房

题目


分析

以完全平方数为源点广搜预处理所有答案,
原来的删除变成了添加,要注意0以及不能删掉数字


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
using namespace std;
const int N=1000011;
int dis[N],q[N],ox[N],head,tail;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline void print(int ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
inline void doit(int y,int x){
	if (dis[y]>dis[x]+1&&ox[y]>=ox[x])
	    dis[y]=dis[x]+1,q[++tail]=y;
}
signed main(){
	memset(dis,42,sizeof(dis)),head=1,tail=0,dis[0]=0;
	for (rr int i=1;i<=1000;++i) dis[i*i]=0,q[++tail]=i*i;
	for (rr int i=10;i<N;i*=10) ox[i]=1; --tail;
	for (rr int i=11;i<N;++i) ox[i]+=ox[i-1];
	while (head<=tail){
		rr int x=q[head++];
		for (rr int i=0;i<10;++i)
		for (rr int j=0;j<6;++j)
		switch (j){
			case 0:doit(x/10*10+i,x); break;
			case 1:doit((x/100*10+i)*10+(x%10),x); break;
			case 2:doit((x/1000*10+i)*100+(x%100),x); break;
			case 3:doit((x/10000*10+i)*1000+(x%1000),x); break;
			case 4:doit((x/100000*10+i)*10000+(x%10000),x); break;
			case 5:doit(i*100000+(x%100000),x); break;
		}
		if (x>99999) continue;
		for (rr int i=0;i<10;++i) doit(x*10+i,x),doit((x/10*10+i)*10+(x%10),x);
		for (rr int i=0;i<10;++i) doit((x/100*10+i)*100+(x%100),x);
		for (rr int i=0;i<10;++i) doit((x/1000*10+i)*1000+(x%1000),x);
		for (rr int i=0;i<10;++i) doit((x/10000*10+i)*10000+(x%10000),x);
		for (rr int i=0;i<10;++i) doit(i*100000+(x%100000),x);
	}
	for (rr int Q=iut();Q;--Q)
	    print(dis[iut()]),putchar(10);
	return 0;
}
posted @ 2020-08-11 16:31  lemondinosaur  阅读(87)  评论(0编辑  收藏  举报