#容斥,广搜#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;
}