博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
51Nod 欢乐手速场1 C 开心的小Q[莫比乌斯函数]
阅读量:6994 次
发布时间:2019-06-27

本文共 3370 字,大约阅读时间需要 11 分钟。

 
(命题人)
 
(测试)
 
基准时间限制:1 秒 空间限制:131072 KB 分值: 80
如果一个数字存在一个约数是完全平方数,那么小Q就认为这个数是有趣的。
小Q喜欢收集有趣的数字,每找到一个有趣的数,小Q就会变得很开心。
小Q发现12是有趣的,18也是有趣的,它们都是36的约数,而在36的约数中,还有3个数是有趣的,它们是4、9、36。
小Q很好奇,在a~b里每个数字各有多少个有趣的约数,由于a和b太大了,所以他只想知道这些个数之和是多少。
例如4有1个有趣的约数,8有2个有趣的约数,9有1个有趣的约数,所以1~10里每个数的有趣约数个数之和是4。
Input
输入数据包括2个数:a, b,中间用空格分隔。(1≤a≤b≤10^9)
Output
输出a~b里每个数字的有趣约数个数之和。
Input示例
1 10
Output示例
4

标解:http://www.51nod.com/contest/problemSolution.html#!problemId=1742 里面的式子改写一开始一直不明白,稍微有点明白了,说说另一种想的方法吧 最暴力的是枚举数字再枚举约数看看是不是平方因子数了 一个简单的优化是枚举约数i,约数i的贡献(倍数的数量)就是[n/i] 但还是会T 一个巧妙的想法是我们枚举是几倍,当前枚举的是i倍,那么满足i倍<=n的数字就是<=[n/i],答案加上<=[n/i]的平方因子数的个数,就是标解中最后的式子了 计算的时候用了两次分块n/(i*i)和n/i做到O(n^2/3) 然而比只一次分块还慢是什么鬼?sqrt的问题吗
#include 
#include
#include
#include
#include
using namespace std;typedef long long ll;const int N=1e5+5;inline int read(){ char c=getchar();ll x=0,f=1; while(c<'0'||c>'9'){
if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f;}int a,b;bool notp[N];int p[N],mu[N];void sieve(int n){ mu[1]=1; for(int i=2;i<=n;i++){ if(!notp[i]) p[++p[0]]=i,mu[i]=-1; for(int j=1;j<=p[0]&&i*p[j]<=n;j++){ notp[i*p[j]]=1; if(i%p[j]==0) break; mu[i*p[j]]=-mu[i]; } } //for(int i=1;i<=n;i++) printf("mu %d %d\n",i,mu[i]); //for(int i=1;i<=n;i++) mu[i]+=mu[i-1];}//int F(int n){// int _=0,r=0,m=sqrt(n);// for(int i=1;i<=m;i=r+1){// r=n/(n/(i*i));// _+=n/(i*i)*(mu[r]-mu[i-1]);// }// return n-_;//}int f(int n){ int _=0,m=sqrt(n); for(int i=1;i<=m;i++) _+=n/(i*i)*mu[i]; return n-_;}ll S(int n){
//printf("n %d\n",n); ll ans=0;int r=0; for(int i=1;i<=n;i=r+1){ r=n/(n/i); ans+=(r-i+1)*f(n/i); //printf("f %d %d %d %d\n",n/i,i,r,f(n/i)); } return ans;}int main(){ //freopen("in","r",stdin); a=read();b=read(); sieve(sqrt(b)+1); printf("%lld",S(b)-S(a-1));}
一次分块
 
#include 
#include
#include
#include
#include
using namespace std;typedef long long ll;const int N=1e5+5;inline int read(){ char c=getchar();ll x=0,f=1; while(c<'0'||c>'9'){
if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f;}int a,b;bool notp[N];int p[N],mu[N];void sieve(int n){ mu[1]=1; for(int i=2;i<=n;i++){ if(!notp[i]) p[++p[0]]=i,mu[i]=-1; for(int j=1;j<=p[0]&&i*p[j]<=n;j++){ notp[i*p[j]]=1; if(i%p[j]==0) break; mu[i*p[j]]=-mu[i]; } } //for(int i=1;i<=n;i++) printf("mu %d %d\n",i,mu[i]); for(int i=1;i<=n;i++) mu[i]+=mu[i-1];}int F(int n){
//printf("F %d\n",n); int _=0,r=0,m=sqrt(n); for(int i=1;i<=m;i=r+1){ r=sqrt(n/(n/(i*i)));//printf("r %d\n",r); _+=n/(i*i)*(mu[r]-mu[i-1]); } return n-_;}ll S(int n){
//printf("n %d\n",n); ll ans=0;int r=0; for(int i=1;i<=n;i=r+1){ r=n/(n/i); ans+=(r-i+1)*F(n/i); //printf("F %d %d %d %d\n",n/i,i,r,F(n/i)); } return ans;}int main(){ //freopen("in","r",stdin); a=read();b=read(); sieve(sqrt(b)+1); printf("%lld",S(b)-S(a-1));}
 

 

 

转载地址:http://xwsvl.baihongyu.com/

你可能感兴趣的文章
Java反射得到属性的值和设置属性的值
查看>>
Linux查看系统版本命令
查看>>
从微博的改版谈网页重构——bigpipe中的页面构建优化
查看>>
layout蒙版
查看>>
Oracle12c多租户如何连接到CDB或PDB、CDB与PDB容器切换
查看>>
Open Xml 读取Excel中的图片
查看>>
(转)IOS 学习笔记 2015-03-23 如何获取IOS程序的系统信息
查看>>
ASSERT()是干什么用的
查看>>
<转>显示图片汇总
查看>>
Flexbox 布局
查看>>
一文搞定Redis高级特性与性能调优
查看>>
并发容器:CopyOnWrite详解以及在KafKa源码中的使用!
查看>>
Jenkins部署maven工程到tomcat简单实例
查看>>
【转载】js清空cookie
查看>>
mysql 分区处理数据
查看>>
HTML5与CSS3
查看>>
爬取IT之家业界新闻
查看>>
Linux-LAMP虚拟主机配置
查看>>
正则表达式基本语法
查看>>
优秀的同伴
查看>>