//拓展欧几里得定理,求ax+by=gcd(a,b)的一组解(x,y),d=gcd(a,b)
void gcd(int a,int b,int &d,int &x,int &y)
{
if(!b){d=a;x=1;y=0;}
else{gcd(b,a%b,d,y,x);y-=x*(a/b);}
}
用法1:
求ax+by=c的整数解。ax+by=gcd(a,b)=g的一组解为(x0,y0),则ax+by=c的一组解为(x0*c/g,y0*c/g)。当c不是g的倍数时无整数解
若(x1,y1)是ax+by=c的一组解,则其任意整数解为(x1+k*bb,y1-k*aa),其中aa=a/gcd(a,b),bb=b/gcd(bb),k为任意整数
//求得a在模n条件下的逆
int inv(int a,int n)
{
int d,x,y;
gcd(a,n,d,x,y);
return d==1?(x+n)%n:-1;
}
或则:
v=pow_mod(a,n-m-1,n);//n为素数,pow_mod(a,n-1,n)=1,费马小定理。所以a^m*a^(n-m-1)=a^(n-1)=1(mod n).
//快速幂求a^b
int pow_mod(int a,int b)
{
int s=1;
while(b)
{
if(b&1)
s=(s*a)%mod;
a=(a*a)%mod;
b=b>>1;
}
return s;
}
//求解模方程a^x=b(mod n)。n为素数,无解返回-1
int log_mod (int a,int b,int n)
{
int m,v,e=1,i;
m=ceil(sqrt(n+0.5));
v=inv(pow_mod(a,m),n);
mapx;
x[1]=0;
for(i=1;i
//hdu 2815 Mod Tree
#include
#include
#include
#include
//中国剩余定理,求得M%A=a,M%B=b,...中的M,其中A,B,C...互质
int china(int a[])
{
int i,j,k,d,ans=0,x,y,M=1;
for(i=0;i
int China(int n)
{
int m1,r1,m2,r2,flag=0,i,d,x,y,c,t;
scanf("%d%d",&m1,&r1);
flag=0;
for(i=1;i
const int maxn=10000001;
const int maxc=700000;
int vis[maxn];//vis[i]=0时,i为素数或者1,否则为合数
int prime[maxc];
//筛素数
void sieve(int n)
{
int m=(int)sqrt(n+0.5);//避免浮点误差
memset(vis,0,sizeof(vis));
for(int i=2;i<=m;i++)if(!vis[i])
for(int j=i*i;j<=n;j+=i)vis[j]=1;
}
//生成素数表,存在prime数组中,返回素数个数
int primes(int n)
{
sieve(n);
int t=0;
for(int i=2;i<=n;i++)if(!vis[i])
prime[t++]=i;
return t;
}
:在O(n)时间复杂度内找出所有的素数
void init()//预处理,找出所有1e7以内的素数,以减少查找1e14范围数的因子的时间
{ //现行筛素数的方法,时间复杂度为O(n)
memset(check,false,sizeof(check));
int i,j;
tot=0;
for(i=2;i<=1e7;i++)
{
if(!check[i])prime[tot++]=i;
for(j=0;j1e7)break;
check[i*prime[j]]=true;
if(i%prime[j]==0)break;
}
}
//printf("%d\n",tot);
//for(i=0;i<20;i++)
// printf("prime[%d]:%d\n",i,prime[i]);
}
,求不超过n且与n互质的正整数个数
int euler_phi(int n)//求单个欧拉函数
{
int m=(int)sqrt(n+0.5);
int i,ans=n;
for(i=2;i<=m;i++)
if(n%i==0)
{
ans=ans/i*(i-1);
while(n%i==0)n/=i;
}
if(n>1)ans=ans/n*(n-1);
return ans;
}
int phi[maxn];
void euler_phi()
{
int i,j,k;
//欧拉函数,phi[i]表示不超过i的与i互质的整数个数
for(i=2;i
,面积S=1/2*|a×b|
int cross(node a,node b,node c)//向量积
{
return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);//向量ac×bc
}
,res数组存凸包上的点。
int convex(int n)
{
sort(e,e+n,cmp);//根据x从小到大排序,x相等时根据y从小到大排序
int m=0,i,j,k;
//求得下凸包,逆时针
for(i=0;i1&&cross(res[m-1],e[i],res[m-2])<=0)m--;
res[m++]=e[i];
}
k=m;
//求得上凸包
for(i=n-2;i>=0;i--)
{
while(m>k&&cross(res[m-1],e[i],res[m-2])<=0)m--;
res[m++]=e[i];
}
if(n>1)m--;//起始点重复。
return m;//返回凸包边界结点数。
}
for(i=0;i<100;i++)
{
m1=l+(r-l)/3;
m2=r-(r-l)/3;
if(find(m1)