题目:阿克克希是求婚总动员的队长,他通过自己的双手,成就了无数年轻人的梦,但他却留下了悲伤的泪水。
求婚是非常费力的,他手上有 P-1个求婚请求,这 i 个人的编号为 [1,P-1],
面对第 i 个人他的求婚麻烦值为:i在模 P 意义下的逆元。
他现在想知道总的麻烦值。
tips: 如果有任意一个编号 i 在模 P 意义下不存在逆元,请输出 AKCniubi
输入格式
一行一个数 P 表示求婚请求总数
输出格式
一行一个数表示总麻烦值
若有数存在无逆元的情况,输出 AKCniubi
数据范围
对于 30% 的数据,P<=1000000
对于 50% 的数据,P<=10000000
对于 100% 的数据,P<=2^31
输出时每行末尾的多余空格,不影响答案正确性
样例输入
3
样例输出
3
题目分析:
1.首先来看逆元是否存在的问题,对于i从[1,p-1],都满足gcd(i,p)=1(即i与p互质)逆元才存在,如果有一个不存 在, 则输出 AKCniubi ,从而我们可知当p为质数时才满足gcd(i,p)=1;如果不是质数,直接输出AKCniubi 。
2.接下来,我们考虑质数的情况,原本准备直接求出所有数的逆元,然后相加,发现超时了,只能另辟蹊径。
测试几个数据之后发现了规律:
(求逆元有多种方法)可以参考这篇博客:https://blog.youkuaiyun.com/qq_44616044/article/details/107252092
如递归:
、
当测试数据为3和5和7和11时,前 p-1 个数的逆元为
由此可发现规律:其逆元之和为前 p-1 个数的和,然后直接用等差数列公式;
AC代码如下
#include<iostream>
using namespace std;
#define ll long long
ll inv(ll a,ll mod)
{
return a==1 ? 1:( mod-mod/a ) * inv(mod%a,mod) % mod;
}
bool isprime(ll x)
{
for(ll i=2;i*i<=x;i++)
{
if(x%i==0)
return false;
}
return true;
}
int main()
{
ios::sync_with_stdio(false);
ll p;
while(cin>>p)
{
if(!isprime(p))//判断是否是质数
{
cout<<"AKCniubi"<<endl;
}
else
{
cout<<(p-1)*p/2<<endl;//等差数列通项公式;
}
}
return 0;
}