题目描述

问有几个无序二元组 (x; y) 满足 xy ≡ 1 (mod P ); 0 ≤ x < P; 0 ≤ y <P。无序二元组是指,如果 P = 10, (3; 7) 和 (7; 3) 只算一次。

输入

一行一个正整数 P。

输出

一行一个数,表示答案。

样例输入

10

样例输出

3

【样例输入 2】

8000000

【样例输出 2】

1600004

【数据范围与子任务】

Subtask1(20pts) $ P \le 10^3 $

Subtask2(30pts) $ P \le 10^5 $

Subtask3(50pts) $ P \le 10^7 $

本来以为是一道神仙数论题,结果是一道SB数论题

首先观察题目给出的式子: $ x \times y \equiv 1 \pmod p $

是不是感觉有一点似曾相识?

如果没有,那说明你逆元学得不太好(或者说没理解)

我们可以发现,这个式子正是在模 $ p $ 意义下 $ x $ 的逆元定义式

但是我们发现,这里的 $ p $ 不一定是一个质数,所以不能直接用逆元的方式来算

但是,我们知道逆元存在的条件的 $ x $ 与模数 $ p $ 互质,所以我们可以通过欧拉函数值 $ \phi (n) $ 来求出部分答案

欧拉函数: $ \phi (n) $ 表示小于等于 $ n $ 的数字中有多少个数字与 $ n $ 互质

欧拉函数可以通过线性筛筛出,代码如下:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio> const int maxn=1e7+5; int prime[maxn],phi[maxn];
int cnt=0,n,m;
bool vis[maxn]; void get_phi(int n){
phi[1]=1;vis[1]=1;
for(int i=2;i<n;++i){
if(!vis[i]){
prime[++cnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=cnt&&i*prime[j]<=n;++j){
vis[i*prime[j]]=true;
if(!(i%prime[j])){
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
} int main(){
scanf("%d%d",&n,&m);
get_phi(n+5);
while(m--){
register int x;
scanf("%d",&x);
puts(vis[x]?"No":"Yes");
}
return 0;
}

也可以使用单个欧拉函数值的求法,复杂度是 $ \Theta \sqrt{n} $

在这个题目中显然后一种比较优秀,这里也同样给出代码:

inline int Euler(int n){
register int res=n,a=n;
for(int i=2;i*i<=a;i++){
if(a%i==0){
res=res/i*(i-1);
while(a%i==0) a/=i;
}
}
if(a>1) res=res/a*(a-1);
return res;
}

千万不要以为这时候这道题就做完了,其实我们还需要考虑一种情况:

当 $ x = y $ 的时候,也即是 $ x^2 \equiv 1 \pmod p $

这种情况也是满足的,所以也要把这种情况统计上,这样这道题才算是AC了

AC代码:

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#define ll long long int mod,ans; inline int Euler(int n){
register int res=n,a=n;
for(int i=2;i*i<=a;i++){
if(a%i==0){
res=res/i*(i-1);
while(a%i==0) a/=i;
}
}
if(a>1) res=res/a*(a-1);
return res;
} int main(){
scanf("%d",&mod);
ans+=Euler(mod);
for(ll i=1;i<=mod;++i) if(i*i%mod==1) ++ans;
printf("%d\n",(ans>>1));
return 0;
}

清北学堂 清北-Day1-R1-Count的更多相关文章

  1. 清北学堂学习总结day1

    上午篇 一.高精度计算: [以下内容先只考虑非负数情况] •高精度加法: 思路:[模拟竖式运算] 注意:[进位] •高精度减法: 思路:[同加法类似,模拟竖式运算,进位变退位] 注意: [结果为负数的 ...

  2. 清北学堂寒假集训DAY1

    第一天,上午讲了些基本的技巧和简单算法,主要就是适应这里. 中午跑到食堂吃了顿“饭”(我并没有挖苦233333),然后回宿舍休息休息 因为 迎接我们的是模拟啊啊啊啊啊阿 下午题一发下来,并没有想象中的 ...

  3. 清北学堂学习总结 day1 数据结构 练习

    1.二叉搜索树 STL set直接做就可以了 2.树状数组+差分数列: codevs 1081 线段树练习 2  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 大师 Maste ...

  4. 清北学堂算法&&数据结构DAY1——知识整理

    简述: 今天主要讲分治(主要是二分).倍增.贪心.搜索,还乱入了爬山算法和模拟退火(汗...) 一.分(er)治(fen): 二分是个在OI中广泛运用的思想,随便举些例子,就足以发现二分的运用的广泛性 ...

  5. 清北学堂 清北-Day3-R2-打架 (fight)

    题目描述 LYK有 \(n\) 个小朋友排成一排.第 \(i\) 个小朋友的战斗力是 $ a_i $,且他们的战斗力互不相同. 战斗力高的会打败战斗力低的. LYK想恶搞这些小朋友们,具体地,它有 \ ...

  6. 清北学堂 清北-Day5-R2-xor

    有 $ n $ 个物品,每个物品有两个属性 $ a_i,b_i $ ,挑选出若干物品,使得这些物品 $ a_i $ 的异或和 $ x \le m \(.问在这一限制下,\) b_i $ 的总和最大可能 ...

  7. 清北学堂 清北-Day1-R2-监听monitor

    题目描述 [背景] 不阅读本题的[背景]并不影响通过本题. 三体信息中没有包含对三体⼈⽣物形态的任何描述,⼈类要在四百多年以后才能真正看到三体⼈.在阅读信息时,叶⽂洁只能把三体⼈想象成⼈类的形象. 1 ...

  8. 清明培训 清北学堂 DAY1

    今天是李昊老师的讲授~~ 总结了一下今天的内容: 1.高精度算法 (1)   高精度加法 思路:模拟竖式运算 注意:进位 优化:压位 程序代码: #include<iostream>#in ...

  9. 清北学堂2017NOIP冬令营入学测试P4745 B’s problem(b)

    清北学堂2017NOIP冬令营入学测试 P4745 B's problem(b) 时间: 1000ms / 空间: 655360KiB / Java类名: Main 背景 冬令营入学测试 描述 题目描 ...

随机推荐

  1. Gossip

    http://www.cnblogs.com/xingzc/p/6165084.html 敬请期待...

  2. 【PgSQL安装(含配置)】PostgreSQL简称PgSQL,是1980以加利福尼亚大学开发的DBMS,严格遵守标准SQL。

    [下载地址]http://www.enterprisedb.com/products-services-training/pgdownload#windows …………………………………………………… ...

  3. win10和Ubuntu双系统安装过程中遇到的问题

    1.安装过程 注意分区问题,很重要 https://blog.csdn.net/baobei0112/article/details/77996570 https://blog.csdn.net/s7 ...

  4. js伪数组转数组

    方法1: 遍历伪数组,在把值push进一个空数组中 方法2: 使用数组的slice方法,它返回的是数组,使用call或apply指向伪数组 var arr = [].slice.call(argume ...

  5. no plugin found for prefix 'tomcat 7' in the current project

    使用maven build编译出错 “no plugin found for prefix 'tomcat 7' in the current project..........” 参照下面方法 ht ...

  6. Flask三种导入配置文件的方式

    # 配置对象,里面定义需要给 APP 添加的一系列配置 class Config(object): DEBUG = True # 从配置对象中加载配置 app.config.from_object(C ...

  7. 列举两种不同类型的Java标识注释,并解释它们之间的区别。

    列举两种不同类型的Java标识注释,并解释它们之间的区别.

  8. Challenge Create a Launch Pad

    在头文件中定义网格体组件和重叠组件 UPROPERTY(VisibleAnywhere,Category="Components") UStaticMeshComponent* M ...

  9. 使用Windows命令行启动关闭服务(net,sc用法)

    下面两个命令最好以管理员方式启动cmd窗口,否则出现权限问题. 1.net用于打开没有被禁用的服务, NET命令是功能强大的以命令行方式执行的工具. 它包含了管理网络环境.服务.用户.登陆大部分重要的 ...

  10. java--GC Root有哪些

    GC管理的主要区域是Java堆,一般情况下只针对堆进行垃圾回收.方法区.JVM栈和Native栈不被GC所管理,因而选择这些非堆区的对象作为GC roots,被GC roots引用的对象不被GC回收. ...