poj 1845 【数论:逆元,二分(乘法),拓展欧几里得,费马小定理】
题意不说了,网上一大堆。此题做了一天,必须要整理一下了。

刚开始用费马小定理做,WA。(poj敢说我代码WA???)(以下代码其实都不严谨,按照数据要求A是可以等于0的,那么结果自然就是0了,需要特判一下,但是poj好像没有为0的数据,能AC。先不改了。)
后来看了好多人的博客,发现很少用费马小定理写的,或者写的代码我看不下去。。就先用那个什么二分等比数列写了一下。
过程也不说了,很多博客都说了。(【1】【2】):
#include<iostream>
#include<cmath>
#define mod 9901
using namespace std;
typedef long long ll;
const int maxn=;
ll p[maxn],r[maxn];
int tot; void Factor(ll n)//质因数分解
{
tot=;
int m=sqrt(n+0.5);
for (int i=;i<=m;i++)
if (n%i==){
p[++tot]=i;
r[tot]=;
while(n%i==){
++r[tot];
n/=i;
}
}
if(n>){
p[++tot]=n;
r[tot]=;
}
} ll qpow(ll a,ll b)//快速幂
{
ll r=;
while(b)
{
if(b&) r=r*a%mod;
b>>=;
a=a*a%mod;
}
return r;
} ll sum(int p,int n)//二分等比数列
{
if(n==)
return ;
if(n&)
return (sum(p,n/)%mod*(+qpow(p,n/+))%mod)%mod;
else
return (sum(p,n/-)%mod*(+qpow(p,n/+))%mod+qpow(p,n/))%mod;
} int main()
{
ll A,B;
cin>>A>>B;
Factor(A);
ll ans=;
for (int i=;i<=tot;i++)
{
ans=(ans%mod*sum(p[i],r[i]*B)%mod)%mod;
}
cout<<ans<<endl;
return ;
}
后来,又看见有人用二分乘法写:
#include<iostream>
#include<cmath>
#define mod 9901
using namespace std;
typedef long long ll;
const int maxn = ;
ll p[maxn], r[maxn];
int tot; void Factor(ll n)
{
tot = ;
int m = sqrt(n + 0.5);
for (int i = ; i <= m; i++)
if (n%i == ) {
p[++tot] = i;
r[tot] = ;
while (n%i == ) {
++r[tot];
n /= i;
}
}
if (n>) {
p[++tot] = n;
r[tot] = ;
}
} ll muti(ll a, ll b, ll m)//二分乘法???求教!!!
{
ll ans = ;
a %= m;
while (b)
{
if (b & )
{
ans = (ans + a) % m;
b--;
}
b >>= ;
a = (a + a) % m;
}
return ans;
} ll qpow(ll a, ll b, ll m)
{
ll ans = ;
a %= m;
while (b)
{
if (b & ) {
ans = muti(ans, a, m);
b--;
}
b >>= ;
a = muti(a, a, m);
}
return ans;
} int main()
{
ll A, B;
cin >> A >> B; Factor(A);
ll ans = ;
for (int i = ; i <= tot; i++)
{
ll m = (p[i] - )*mod;
ans *= (qpow(p[i], r[i] * B + , m) - + m) / (p[i] - );
ans %= mod;
}
cout << ans << endl;
return ;
}
说实话我现在还不懂为什么要二分乘法?啥子是二分乘法?这是ACdreamer(【1】)(应该是个大牛吧!!!)里面写的,后来也到过其他博客写过,代码都极其相似。ACdreamer说mb会可能会超int范围,所以快速幂时二分乘法。???我现在也很懵逼,mb超int怎么了?不超long long不就行了?难道超int模会出错?求解释啊!!!
后来,又看到了有人用拓展欧几里得:
#include<iostream>
#include<cmath>
#define mod 9901
using namespace std;
typedef long long ll;
const int maxn=;
ll p[maxn],r[maxn];
int tot; void Factor(ll n)
{
tot=;
int m=sqrt(n+0.5);
for (int i=;i<=m;i++)
if (n%i==){
p[++tot]=i;
r[tot]=;
while(n%i==){
++r[tot];
n/=i;
}
}
if(n>){
p[++tot]=n;
r[tot]=;
}
} ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==){
x=,y=;
return a;
}
int ret=exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
return ret;
} ll inv(ll n)
{
n%=mod;
ll a=n,b=mod,x,y;
exgcd(a,b,x,y);
x=(x%mod+mod)%mod;
return x;
} ll qpow(ll a,ll b)
{
ll r=;
while(b)
{
if(b&) r=a*r%mod;
b>>=;
a=a*a%mod;
}
return r;
} int main()
{
ll A,B;
cin>>A>>B; Factor(A);
ll ans=;
for (int i=;i<=tot;i++)
{
if(p[i]%mod==){//!!!
ans*=(r[i]*B+)%mod;
ans%=mod;
}else{
ans*=((qpow(p[i],r[i]*B+)-+mod)%mod*inv(p[i]-))%mod;
ans%=mod;
}
}
cout<<ans<<endl;
return ;
}
能拓展欧几里得那么费马小定理也应该差不多啊!!!
所以回头我又写了费马小定理的:
#include<iostream>
#include<cmath>
#define mod 9901
using namespace std;
typedef long long ll;
const int maxn=;
ll p[maxn],r[maxn];
int tot; void Factor(ll n)
{
tot=;
int m=sqrt(n+0.5);
for (int i=;i<=m;i++)
if (n%i==){
p[++tot]=i;
r[tot]=;
while(n%i==){
++r[tot];
n/=i;
}
}
if(n>){
p[++tot]=n;
r[tot]=;
}
} ll qpow(ll a,ll b)
{
ll r=;
a%=mod;
while(b)
{
if(b&) r=a*r%mod;
b>>=;
a=a*a%mod;
}
return r;
} int main()
{
ll A,B;
cin>>A>>B; Factor(A);
ll ans=;
for (int i=;i<=tot;i++)
{ if(p[i]%mod==){//!!!
ans*=(r[i]*B+)%mod;
ans%=mod;
}else{
ans*=((qpow(p[i],r[i]*B+)-+mod)%mod*qpow(p[i]-,mod-)%mod)%mod;//直接用费马小定理求逆元,qpow(p[i]-1,mod-2);
ans%=mod;
}
}
cout<<ans<<endl;
return ;
}
直到这时,我才明白我以前写费马为什么错了。因为当素因子p[i]%mod==1时,求逆元的结果是错的,或者就像有的博客说这时是求不出逆元的。因为这时qpow(p[i]-1,mod-2)的结果一定为0。因为当求(1+p^1+p^2+p^3...+p^r)%mod时,由于p%mod==1,所以每项%mod都是1,结果就是r+1。也就是上面两个代码特判的结果:r[i]*B+1。
最后提供一个数据: 59407 3
我的结果是:4
没有特判的话,结果会是0。这个就是我找到的第一个大于9901且%9901=1的质数。
感谢网上的广大博客,终于让我看了一天后悟出了这一点。。。。。
本来想巩固一下逆元的概念,结果ACdreamer里面看到的这道题弄了一天。。。
希望以后能看到这个文章的朋友们能够给我解释一下为什么要二分乘法?不理解啊!先谢谢!!
谢谢这些博客们,有可能没有一一列出,你们至多至少都给了我一点启发和帮助!也希望你们写博客的时候在关键能多说几句>_<.
【1】http://blog.csdn.net/acdreamers/article/details/8220787
【2】http://blog.csdn.net/lyy289065406/article/details/6648539
【3】http://blog.csdn.net/a601025382s/article/details/12233213
【4】http://blog.csdn.net/hlmfjkqaz/article/details/9735143
【5】http://www.cnblogs.com/mjy0724/p/4371752.html
【6】http://m.blog.csdn.net/kbdwo/article/details/9798193
【7】http://www.cnblogs.com/linyujun/p/5194184.html
poj 1845 【数论:逆元,二分(乘法),拓展欧几里得,费马小定理】的更多相关文章
- UVA10200-Prime Time/HDU2161-Primes,例题讲解,牛逼的费马小定理和欧拉函数判素数。
10200 - Prime Time 此题极坑(本菜太弱),鉴定完毕,9遍过. 题意:很简单的求一个区间 ...
- 【bzoj5118】Fib数列2 费马小定理+矩阵乘法
题目描述 Fib定义为Fib(0)=0,Fib(1)=1,对于n≥2,Fib(n)=Fib(n-1)+Fib(n-2) 现给出N,求Fib(2^n). 输入 本题有多组数据.第一行一个整数T,表示数据 ...
- 【BZOJ】3398: [Usaco2009 Feb]Bullcow 牡牛和牝牛(排列组合+乘法逆元+欧拉定理/费马小定理)
http://www.lydsy.com/JudgeOnline/problem.php?id=3398 以下牡牛为a,牝牛为b. 学完排列计数后试着来写这题,“至少”一词可以给我们提示,我们可以枚举 ...
- CodeForces 300C Beautiful Numbers(乘法逆元/费马小定理+组合数公式+高速幂)
C. Beautiful Numbers time limit per test 2 seconds memory limit per test 256 megabytes input standar ...
- 简记乘法逆元(费马小定理+扩展Euclid)
乘法逆元 什么是乘法逆元? 若整数 \(b,m\) 互质,并且\(b|a\) ,则存在一个整数\(x\) ,使得 \(\frac{a}{b}\equiv ax\mod m\) . 称\(x\) 是\( ...
- BZOJ_[HNOI2008]_Cards_(置换+Burnside引理+乘法逆元+费马小定理+快速幂)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1004 共n个卡片,染成r,b,g三种颜色,每种颜色的个数有规定.给出一些置换,可以由置换得到的 ...
- hdu1576-A/B-(同余定理+乘法逆元+费马小定理+快速幂)
A/B Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- HDU 3923 Invoker(polya定理+乘法逆元(扩展欧几里德+费马小定理))
Invoker Time Limit : 2000/1000ms (Java/Other) Memory Limit : 122768/62768K (Java/Other) Total Subm ...
- hihocoder #1698 假期计划 (排列组合+费马小定理+乘法逆元)
Description 小Ho未来有一个为期N天的假期,他计划在假期中看A部电影,刷B道编程题.为了劳逸结合,他决定先拿出若干天看电影,再拿出若干天刷题,最后再留若干天看电影.(若干代指大于0) 每 ...
随机推荐
- Luogu P3254 圆桌问题(最大流)
P3254 圆桌问题 题面 题目描述 假设有来自 \(m\) 个不同单位的代表参加一次国际会议.每个单位的代表数分别为 \(r_i (i =1,2,--,m)\) . 会议餐厅共有 \(n\) 张餐桌 ...
- 『Power AI by AI』 PAI-AutoML2.0重磅发布
PAI-AutoML调参服务是通过算法的方式解放用户调节算法参数的工作.自2018年8月发布PAI-AutoML1.0版本以来,该功能已经帮助众多PAI的中小企业用户提升了模型的准确性,得到了不错的反 ...
- TZ_16_Vue父子组件之间的通信
1.父向子传递props,该如何传递 <!DOCTYPE html> <html lang="en"> <head> <meta char ...
- 移动端适配(rem单位定义方法)
注:移动端必须写: <meta name="viewport" content="width=device-width, user-scalable=no, ini ...
- [转]json对象详解
json(javascript object notation)全称是javascript对象表示法,它是一种数据交换的文本格式,而不是一种编程语言,用于读取结构化数据.2001年由Douglas C ...
- JS倒计时-毫秒
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" ...
- maven的hibernate4 依赖
<!-- 添加Hibernate4依赖 --> <dependency> <groupId>org.hibernate</groupId> <ar ...
- 洛谷P1006 NOIP提高组2008 传纸条
P1006 传纸条 题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n 列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无 ...
- mac 下的 homebrew
如果安装了macport 就不能安装homebrew ,必须先卸载macport $ sudo port -f uninstall installed$ sudo rm -rf \/opt/local ...
- C# 如何比较版本号大小
最近遇到了一个数据迁移的问题,因为配置文件的结构发生变化,所以要把低版本的用户数据保存下来,存到最新版本中去. 这里就有一个比较版本号大小的问题了,网上乱七八糟算法一堆,大致意思就是用分割字符串的方法 ...