OI常用模板

0. IO优化

0.1 读入优化

char Getchar(){
    static char now[1<<20],*S,*T;
    if (T==S){
        T=(S=now)+fread(now,1,1<<20,stdin);
        if (T==S) return EOF;
    }
    return *S++;
}
int read(){
    int x=0,f=1;
    char ch=Getchar();
    while (ch<'0'||ch>'9'){
        if (ch=='-') f=-1;
        ch=Getchar();
    }
    while (ch<='9'&&ch>='0') x=x*10+ch-'0',ch=Getchar();
    return x*f;
}
char readop(){
    char ch=Getchar();
    while (ch<'A'||ch>'Z') ch=Getchar();
    return ch;
}

0.2 输出优化

char pbuf[100000],*pp=pbuf;
void pc(const char c) {
    if (pp-pbuf==100000) fwrite(pbuf,1,100000,stdout),pp=pbuf;
    *pp++=c;
}
void write(int x) {
    static int sta[35];
    if (x<0){
        pc('-');
        x=-x;
    }
    int top=0;
    do{
        sta[top++]=x%10;
    x/=10;
    } while(x);
    while (top) pc(sta[--top]+'0');
}
void myfflush(){
    fwrite(pbuf,1,pp-pbuf,stdout);
}

1. 数论

1.1 快速幂

ll qpow(ll x,ll a){
    ll res=1;
    while (a){
        if (a&1) res=res*x%Mod;
        x=x*x%Mod; a>>=1;
    }
    return res;
}

1.2 gcd

int gcd(int a,int b){
    if (!b) return a;
    return gcd(b,a%b);
}

1.3 exgcd

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

1.4 Pollard Rho

  • 输出 \(n\) 的最大质因子(\(1\leqslant n\leqslant 10^{18}\)
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#define ctz __builtin_ctzll
using namespace std;
typedef long long ll;
ll ans;
/*inline ll mul(ll x,ll y,ll Mod){
    ll ret=x*y-((ll)((long double)x/Mod*y+0.5))*Mod;
    return (ret%Mod+Mod)%Mod;
}*/
inline ll mul(ll x,ll y,ll p){
    return (__int128)x*y%p;
}
inline ll qpow(ll x,ll a,ll Mod){
    ll res=1;
    while (a){
        if (a&1) res=mul(res,x,Mod);
        x=mul(x,x,Mod); a>>=1;
    }
    return res;
}
/*
int rd(){ return (rand()<<15)|rand();}
ll gcd(ll a,ll b){
    if (!a) return b;
    if (!b) return a;
    int t=ctz(a|b);
    a>>=ctz(a);
    do{
        b>>=ctz(b);
        if (a>b) swap(a,b);
        b-=a;
    } while (b);
    return a<<t;
}*/
inline ll rdm(){ return 1ll*rand()<<31|rand();}
ll gcd(ll x,ll y){
	if (!y) return x;
	return gcd(y,x%y);
}
bool Miller_Rabin(ll n){
    if (n==2||n==3) return true;
    if (!(n&1)||(n==1)||!(n%3)) return false;
    ll p=n-1,m=0;
    while (!(p&1)) p>>=1,++m;
    int Case=8;
    while (Case--){
        ll lst=qpow(rdm()%(n-1)+1,p,n),now=lst;
        for (int i=1;i<=m;i++){
            now=mul(now,now,n);
            if (now==1&&lst!=1&&lst!=n-1) return false;
            lst=now;
        }
        if (now!=1) return false;
    }
    return true;
}
ll Pollard_Rho(ll n,int c){
    ll i=1,k=2,x=rand()%(n-1)+1,y=x,sum=1;
    while (true){
        i++; x=(mul(x,x,n)+c)%n;
        sum=mul(sum,(y-x+n)%n,n);
        if (x==y||!sum) return n;
        if (i==k||i%127==0){
            int d=gcd(sum,n);
            if (d!=1) return d; 
            if (i==k){ y=x; k<<=1;}
        }
    }
}
void work(ll n){
    if (n<=ans) return;
    if (Miller_Rabin(n)){
        ans=max(ans,n);
        return;
    }
    ll tmp=n;
    while (tmp==n) tmp=Pollard_Rho(n,rand()%n);
    while (n%tmp==0) n/=tmp;
    work(tmp); work(n);
}
int main(){
    srand(time(NULL));
    int T; ll x;
    scanf("%d",&T);
    while (T--){
        scanf("%lld",&x);
        if (Miller_Rabin(x)){ puts("Prime"); continue;}
        ans=0; work(x);
        printf("%lld\n",ans);
    }
    return 0;
}

2.数据结构

2.1 树状数组

单点加区间查询

void add(int *tree,int x,int y){
    for (;x<=N;x+=x&-x) tree[x]+=y;
}
int getsum(int *tree,int x){
    int sum=0;
    for (;x;x-=x&(-x)) sum+=tree[x];
    return sum;
}

区间加区间查询

/*
    b[i]=a[i]-a[i-1]
    a[1] + a[2] + ... + a[n]
    = (b[1]) + (b[1]+b[2]) + ... + (b[1]+b[2]+...+b[n])
    = n*b[1] + (n-1)*b[2] +... +b[n]
    = n * (b[1]+b[2]+...+b[n]) - (0*b[1]+1*b[2]+...+(n-1)*b[n])
    sum1[i] = \sum b[i],sum2[i] = \sum b[i]*(i-1)
*/
int n,a[N];
int sum1[N],sum2[N];
void change(int x,int y){
    for (int i=x;i<=n;i+=(i&-i)){
        sum1[i]+=y;
        sum2[i]+=y*(x-1);
    }
}
void range_change(int l,int r,int y){
    change(l,y);
    change(r+1,-y);
}
int query(int x){
    int res=0;
    for (int i=x;i>=1;i-=(i&-i)) res+=x*sum1[i]-sum2[i];
    return res;
}
int range_query(int l,int r){ return query(r)-query(l-1);}
 
int main(){
    for (int i=1;i<=n;i++) change(i,a[i]-a[i-1]);
    //[l,r] +x        range_change(l,r,x); 
    //sum(l,r)        range_query(l,r)
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hydd-233/p/12908607.html
OI