逆元

 

//b^(-1)是 b的逆元素 (%p)
//2的逆元素是15 (%29) ,因为2*15=30=1 %29
//21的逆元素是18 (%29) ,因为21*18=378%29=1 %29

//%运算法则 1. (a*b) %p= ( a%p) *(b%p)
//%运算法则 2. (a/b) %p= ( a *b^(-1)%p) !!!!
// b*b^(-1)= 1 (mod p) 若求b*b的逆元 ,则等同于 ((b*b)%p)*(b*b)^(-1)=1(mod p)

#define LL long long
LL ex_gcd(LL a,LL b,LL &x,LL &y){
if(b==0){
x=1;y=0;
return a;
}
LL g,t;
g=ex_gcd(b,a%b,x,y);
t=x;
x=y;
y=t-a/b*y;
return g;
}
LL niyuan(LL b,LL p){
LL x,y;
ex_gcd(b,p,x,y);
return x=(x%p+p)%p;
}



 

UVALive 5798 

逆元+树状数组

View Code
#include<iostream>
#include<cstring>
#include <cstdio>
#include<string>
#include<queue>
#include<vector>
#include<map>
#include <set>
#include<ctime>
#include<cmath>
#include <cstdlib>
#include<algorithm>
#include <iomanip>
#include <bitset>
using namespace std;
#define LL long long

#define lowbit(x) ((x)&(-(x)))
const LL Max = 100005;

LL ex_gcd(LL a,LL b,LL &x,LL &y){
if(b==0){
x=1;y=0;
return a;
}
LL g,t;
g=ex_gcd(b,a%b,x,y);
t=x;
x=y;
y=t-a/b*y;
return g;
}

LL n, ar[Max];

void add(LL i, LL w){
while(i <= n){
ar[i] += w;
i += lowbit(i);
}
}

LL sum(LL i){
LL ans = 0;
while(i > 0){
ans += ar[i];
i -= lowbit(i);
}
return ans;
}
void init(){
memset(ar, 0, sizeof(ar));
}
LL m[Max],B_[Max];
int main(){
LL B,P,L,N;
while(scanf("%lld%lld%lld%lld",&B,&P,&L,&N)){
if(!B&&!P&&!L&&!N) return 0;

memset(ar,0,sizeof(ar));
m[L]=1; n=L;
for(LL i=L-1;i>=1;i--) m[i]= (B*m[i+1]) %P;
for(LL i=L;i>=1;i--){
LL x,y;
ex_gcd(m[i],P,x,y);
x=(x%P+P)%P;
B_[i]=x;
}
while(N--){
char s[10];
scanf("%s",s);
if(s[0]=='E'){
LL u,v;
scanf("%lld%lld",&u,&v);
LL x=( v*m[u] )%P-( sum(u)-sum(u-1) );
add(u,x);
}else {
LL u,v;
scanf("%lld%lld",&u,&v);
LL x=sum(v)-sum(u-1);
x=(x%P+P)%P;
printf("%lld\n",((x*B_[v])%P+P)%P);
}
}
printf("-\n");
}
}



posted @ 2012-04-07 19:46  HaoHua_Lee  阅读(230)  评论(0编辑  收藏  举报