zoukankan      html  css  js  c++  java
  • 【ybt金牌导航8-4-1】整数个数 / 欧拉函数例题

    整数个数

    题目链接:ybt金牌导航8-4-1

    题目大意

    给你一个数 n,求满足一下条件的数个数:
    要小于 n,要不是 n 的约数,不能与 n 互质。

    思路

    你看到互质,自然会想到欧拉函数。

    但是它是不能互质啊,而且它说不是约数也很烦。

    那简单,我们容斥一下,用全部的(根据小于 (n)(n-1) 个)减去是 (n) 的约数(n) 互质的个数就好了。

    那算约数的时候你会把 (n) 也算作约数,但你前面的条件是小于 (n),那就要继续容斥,这里算的是减的,那你就要加回一个 (1)

    然后你算约数和算互质的时候会都算到 (1),那也容斥,加回 (1)

    那这样就可以直接减约数个数和互质个数再根据上面容斥就可以了。

    接着就是怎么求互质个数,也就是欧拉函数要怎么算。

    这里给出一种算单个的方法。
    (varphi(i)=i imesdfrac{p_1-1}{p_1} imes... imesdfrac{p_m-1}{p_m})
    (p_i) 是它的质数因子)

    原理大概就是它不能出现任何因子,而因子由素数因子构成。
    然后就类似容斥,你某个质数 (p_i)(1sim i) 划分成许多长度为 (p_i) 的区间,然后每个区间都有个位置不能选(就是那个位置是 (p_i) 的倍数)。
    然后每个质数因子都这样,就是这个公式了。

    代码

    #include<cstdio>
    #define ll long long
    
    using namespace std;
    
    ll n, ans;
    
    ll phi(ll x) {//求n的phi值
    	int re = x;
    	for (int i = 2; i * i <= x; i++)
    		if (n % i == 0) {
    			re = re / i * (i - 1);
    			while (n % i == 0) n /= i;
    		}
    	if (n >> 1)
    		re = re / n * (n - 1);
    	return re;
    }
    
    int main() {
    	scanf("%d", &n);
    	ans = n - 1;//满足小于 n 的有 n-1 个
    	
    	for (ll i = 1; i * i <= n; i++)//求 n 因子的个数
    		if (n % i == 0) {
    			ans -= 2;
    			if (i * i == n) ans++;
    		}
    	ans++;//前面求的时候把 n 也算个进去,减多了,要加回去
    	
    	ans -= phi(n);//求与 n 互质的数的个数(n 的 phi 值)
    	
    	ans++;//求因子和求互质的地方都算了 1,重复了要加回去。
    	
    	printf("%lld
    ", ans);
    	
    	return 0;
    }
    
  • 相关阅读:
    7月自动化测试公开课通知
    招高级自动化测试工程师
    招聘软件开发工程师/开发实习生
    Selenium关键字驱动测试框架Demo(Java版)
    Eclipse+Selenium自动化测试脚本设计V1.0
    WebDriver基本API使用(基于Java)V1.0
    测试体系建设 免费咨询服务
    UFTQTP 12 新特性
    招聘自动化测试工程师
    AppScan学习笔记
  • 原文地址:https://www.cnblogs.com/Sakura-TJH/p/YBT_JPDH_8-4-1.html
Copyright © 2011-2022 走看看