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) 每 ...
随机推荐
- 「G2016 SCOI2018 Round #2」B
传送门 杜教筛的简单题. 莫比乌斯反演一下,然后杜教筛.
- 计算机组成原理(电脑硬件&语言分类)
计算机组成原理 一.电脑硬件配置 CPU :中央处理器(人类的大脑) -飞机 内存:存放一些临时数据(人类的短暂记忆-右脑) -高铁 硬盘:存储永久数据(左脑-长期记忆) - 汽车 输入输出:键盘鼠标 ...
- Java问题解读系列之IO相关---Java深拷贝和浅拷贝
前几天和棒棒童鞋讨论Java(TA学的是C++)的时候,他提到一个浅拷贝和深拷贝的问题,当时的我一脸懵圈,感觉自己学Java居然不知道这个知识点,于是今天研究了一番Java中的浅拷贝和深拷贝,下面来做 ...
- bzoj3064/洛谷P4314 CPU监控【线段树】
好,长草博客被催更了[?] 我感觉这题完全可以当作线段树3 线段树2考加法和乘法标记的下放顺序,这道题更丧心病狂[?] 很多人可能跟我一样,刚看到这道题秒出思路:打一个当前最大值一个历史最大值不就完事 ...
- Chrome谷歌浏览器调试
Chrome浏览器调试技巧 https://blog.csdn.net/u014727260/article/details/53231298
- vue和element全局loading
http请求的代码如下: import axios from 'axios' import { Message} from 'element-ui' import store from '../sto ...
- 【模板】 递归线段树 [2017年五月计划 清北学堂51精英班Day4]
P3372 [模板]线段树 1 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别 ...
- bzoj 1191 [HNOI2006]超级英雄Hero——二分图匹配
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1191 不就是个最大匹配么. 结果WA得不行. 看TJ后发现题面上说了一旦没回答出一道题就结束 ...
- DFA算法实现敏感词过滤
DFA算法:即确定有穷自动机,简单点说就是,它是是通过event和当前的state得到下一个state,即event+state=nextstate.理解为系统中有多个节点,通过传递进入的event, ...
- HttpClient实现远程调用
在项目中,我们常常遇到远程调用的问题,一个模块总是无法单独存在,总需要调用第三方或者其他模块的接口.这里我们就涉及到了远程调用. 原来在 ITOO中,我们是通过使用EJB来实现远程调用的 ...