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;
}