加减乘除
1 //compare比较函数:相等返回0,大于返回1,小于返回-1 2 int compare(string str1,string str2) 3 { 4 if(str1.length()>str2.length()) return 1; 5 else if(str1.length()<str2.length()) return -1; 6 else return str1.compare(str2); 7 } 8 //高精度加法 9 //只能是两个正数相加 10 string add(string str1,string str2)//高精度加法 11 { 12 string str; 13 14 int len1=str1.length(); 15 int len2=str2.length(); 16 //前面补0,弄成长度相同 17 if(len1<len2) 18 { 19 for(int i=1;i<=len2-len1;i++) 20 str1="0"+str1; 21 } 22 else 23 { 24 for(int i=1;i<=len1-len2;i++) 25 str2="0"+str2; 26 } 27 len1=str1.length(); 28 int cf=0; 29 int temp; 30 for(int i=len1-1;i>=0;i--) 31 { 32 temp=str1[i]-'0'+str2[i]-'0'+cf; 33 cf=temp/10; 34 temp%=10; 35 str=char(temp+'0')+str; 36 } 37 if(cf!=0) str=char(cf+'0')+str; 38 return str; 39 } 40 //高精度减法 41 //只能是两个正数相减,而且要大减小 42 string sub(string str1,string str2)//高精度减法 43 { 44 string str; 45 int tmp=str1.length()-str2.length(); 46 int cf=0; 47 for(int i=str2.length()-1;i>=0;i--) 48 { 49 if(str1[tmp+i]<str2[i]+cf) 50 { 51 str=char(str1[tmp+i]-str2[i]-cf+'0'+10)+str; 52 cf=1; 53 } 54 else 55 { 56 str=char(str1[tmp+i]-str2[i]-cf+'0')+str; 57 cf=0; 58 } 59 } 60 for(int i=tmp-1;i>=0;i--) 61 { 62 if(str1[i]-cf>='0') 63 { 64 str=char(str1[i]-cf)+str; 65 cf=0; 66 } 67 else 68 { 69 str=char(str1[i]-cf+10)+str; 70 cf=1; 71 } 72 } 73 str.erase(0,str.find_first_not_of('0'));//去除结果中多余的前导0 74 return str; 75 } 76 //高精度乘法 77 //只能是两个正数相乘 78 string mul(string str1,string str2) 79 { 80 string str; 81 int len1=str1.length(); 82 int len2=str2.length(); 83 string tempstr; 84 for(int i=len2-1;i>=0;i--) 85 { 86 tempstr=""; 87 int temp=str2[i]-'0'; 88 int t=0; 89 int cf=0; 90 if(temp!=0) 91 { 92 for(int j=1;j<=len2-1-i;j++) 93 tempstr+="0"; 94 for(int j=len1-1;j>=0;j--) 95 { 96 t=(temp*(str1[j]-'0')+cf)%10; 97 cf=(temp*(str1[j]-'0')+cf)/10; 98 tempstr=char(t+'0')+tempstr; 99 } 100 if(cf!=0) tempstr=char(cf+'0')+tempstr; 101 } 102 str=add(str,tempstr); 103 } 104 str.erase(0,str.find_first_not_of('0')); 105 return str; 106 } 107 108 //高精度除法 109 //两个正数相除,商为quotient,余数为residue 110 //需要高精度减法和乘法 111 void div(string str1,string str2,string "ient,string &residue) 112 { 113 quotient=residue="";//清空 114 if(str2=="0")//判断除数是否为0 115 { 116 quotient=residue="ERROR"; 117 return; 118 } 119 if(str1=="0")//判断被除数是否为0 120 { 121 quotient=residue="0"; 122 return; 123 } 124 int res=compare(str1,str2); 125 if(res<0) 126 { 127 quotient="0"; 128 residue=str1; 129 return; 130 } 131 else if(res==0) 132 { 133 quotient="1"; 134 residue="0"; 135 return; 136 } 137 else 138 { 139 int len1=str1.length(); 140 int len2=str2.length(); 141 string tempstr; 142 tempstr.append(str1,0,len2-1); 143 for(int i=len2-1;i<len1;i++) 144 { 145 tempstr=tempstr+str1[i]; 146 tempstr.erase(0,tempstr.find_first_not_of('0')); 147 if(tempstr.empty()) 148 tempstr="0"; 149 for(char ch='9';ch>='0';ch--)//试商 150 { 151 string str,tmp; 152 str=str+ch; 153 tmp=mul(str2,str); 154 if(compare(tmp,tempstr)<=0)//试商成功 155 { 156 quotient=quotient+ch; 157 tempstr=sub(tempstr,tmp); 158 break; 159 } 160 } 161 } 162 residue=tempstr; 163 } 164 quotient.erase(0,quotient.find_first_not_of('0')); 165 if(quotient.empty()) quotient="0"; 166 }
扩展欧几里得
1 // ax+by=gcd(a,b) 2 // d为a和b的最大公因数 3 void exgcd(LL a,LL b,LL &d,LL &x,LL &y) 4 { 5 if(!b) 6 { 7 d=a;x=1;y=0; 8 } 9 else { 10 exgcd(b,a%b,d,y,x); 11 y-=x*(a/b); 12 } 13 }
1 // ax+by=gcd(a,b) 2 LL exgcd(LL a,LL &x, LL b, LL &y) 3 { 4 LL x1=0,y1=1,x0=1,y0=0; 5 LL r=(a%b+b)%b; 6 LL q=(a-r)/b; 7 x=0;y=1; 8 while(r) 9 { 10 x=x0-q*x1; 11 y=y0-q*y1; 12 x0=x1;y0=y1; 13 x1=x;y1=y; 14 a=b;b=r; 15 r=a%b;q=(a-r)/b; 16 } 17 return b; //返回a和b的最大公因数 18 }
如果得到ax ≡ c (mod b)的某一特解X,那么令r = b/gcd(a, b),可知x在[0, r-1]上有唯一解
所以用x = (X % r + r) % r就可以求出最小非负整数解x
求解n个方程x%m[i]=b[i],返回x
1 void exgcd(int a,int b,int &d,int &x,int &y){ 2 if(!b){d=a;x=1;y=0;} 3 else {exgcd(b,a%b,d,y,x);y-=x*(a/b);} 4 } 5 // 求解n个方程x%m[i]=b[i],返回x 6 int solve(int* b,int* m,int n){ 7 int m1=m[0],b1=b[0];; 8 for(int i=1;i<n;i++){ 9 int m2=m[i],b2=b[i]; 10 int g,x,y; 11 exgcd(m1,m2,g,x,y); 12 int c=b2-b1; 13 if(c%g) return -1; //无解 14 x=x*(c/g); 15 int r=m2/g; 16 x=(x%r+r)%r; 17 b1+=m1*x; 18 m1*=m2/g; 19 b1%=m1; 20 } 21 return (b1%m1+m1-1)%m1+1; //返回正整数解 22 }
中国剩余定理
求解x%m[i]=b[i],其中m[i]两两互质
1 // 求解x%m[i]=b[i],其中m[i]两两互质 2 int china(int* b,int* m,int n){ 3 int M=1,ans=0; 4 for(int i=0;i<n;i++) M*=m[i]; 5 for(int i=0;i<n;i++){ 6 int N=M/m[i]; 7 int g,x,y; 8 exgcd(N,m[i],g,x,y); 9 ans=(ans+b[i]*N*x)%M; 10 } 11 return (ans+M)%M; 12 }
BSGS算法
求解Ax≡B(mod C),C是素数。
1 #define ll long long 2 const int mod=99991; 3 ll head[mod],nex[mod]; 4 ll cnt; 5 ll hs[mod],id[mod]; 6 void init(){ 7 memset(head,-1,sizeof(head)); 8 cnt=0; 9 } 10 void insert_(ll x,ll i){ 11 hs[cnt]=x;id[cnt]=i; 12 ll u=x%mod; 13 nex[cnt]=head[u]; 14 head[u]=cnt++; 15 } 16 ll find_(ll x){ 17 int u=x%mod; 18 for(int i=head[u];~i;i=nex[i]){ 19 if(hs[i]==x) return id[i]; 20 } 21 return -1; 22 } 23 //求解A^x≡B(mod C),返回x,若无解返回-1 24 ll bsgs(ll a,ll b,ll c){ 25 if(b==1) return 0; 26 ll m=ceil(sqrt(c*1.0)); 27 ll q=1; 28 for(ll i=0;i<=m;i++){ 29 if(i==0) insert_(b%c,i); 30 else{ 31 q=q*a%c; 32 insert_(q*b%c,i); 33 } 34 } 35 ll temp=1; 36 for(ll i=1;i<=m;i++){ 37 temp=temp*q%c; 38 ll j=find_(temp); 39 if(j!=-1) return i*m-j; 40 } 41 return -1; 42 }
扩展BSGS算法
求解Ax≡B(mod C)。
1 #define ll long long 2 const int mod=99991; 3 ll head[mod],nex[mod]; 4 ll cnt; 5 ll hs[mod],id[mod]; 6 void init(){ 7 memset(head,-1,sizeof(head)); 8 cnt=0; 9 } 10 void insert_(ll x,ll i){ 11 hs[cnt]=x;id[cnt]=i; 12 ll u=x%mod; 13 nex[cnt]=head[u]; 14 head[u]=cnt++; 15 } 16 ll find_(ll x){ 17 int u=x%mod; 18 for(int i=head[u];~i;i=nex[i]){ 19 if(hs[i]==x) return id[i]; 20 } 21 return -1; 22 } 23 ll gcd(ll a,ll b){ 24 ll r=a%b; 25 while(r){a=b;b=r;r=a%b;} 26 return b; 27 } 28 //求解a^x≡b(mod c),返回x,无解返回-1 29 ll BSGS(ll a,ll b,ll c){ 30 a%=c;b%=c; 31 if(b==1) return 0; 32 ll g=1,d=1,k=0; 33 while((g=gcd(a,c))!=1){ 34 if(b%g) return -1; 35 b/=g;c/=g; 36 k++; 37 d=d*(a/g)%c; 38 if(b==d) return k; 39 } 40 ll m=ceil(sqrt(c*1.0)),q=1; 41 for(ll i=0;i<=m;i++){ 42 if(i==0) insert_(b,i); 43 else { 44 q=q*a%c; 45 insert_(q*b%c,i); 46 } 47 } 48 for(ll i=1;i<=m;i++){ 49 d=d*q%c; 50 ll j=find_(d); 51 if(j!=-1) return i*m-j+k; 52 } 53 return -1; 54 }
欧拉函数(求与n互质的数有多少个)
1 //返回n的欧拉函数值 2 int phi(int n){ 3 int m=sqrt(n+0.5); 4 int ans=n; 5 for(int i=2;i<=m;i++) if(n%i==0){ 6 ans=ans/i*(i-1); 7 while(n%i==0) n/=i; 8 } 9 if(n>1) ans=ans/n*(n-1); 10 return ans; 11 } 12 13 //生成1到n的欧拉函数值 14 void get_phi(int n,int *phi){ 15 for(int i=2;i<=n;i++) phi[i]=0; 16 phi[1]=1; 17 for(int i=2;i<=n;i++) if(!phi[i]]){ 18 for(int j=i;j<=n;j+=i){ 19 if(!phi[j]) phi[j]=j; 20 phi[j]=phi[j]/i*(i-1); 21 } 22 } 23 }
高斯消元
1 const int inf=0x3f3f3f3f; 2 //const int mod=2; 3 const int maxn=25; 4 int a[maxn][maxn]; //系数 5 int x[maxn],free_x[maxn]; 6 int n,m; 7 /* 8 int gcd(int a,int b){ 9 return b==0?a:gcd(b,a%b); 10 } 11 int lcm(int a,int b){ 12 return a/gcd(a,b)*b; 13 } 14 void exgcd(int a,int b,int &d,int &x,int &y){ 15 if(!b){d=a;x=1;y=0;} 16 else {exgcd(b,a%b,d,y,x); y-=x*(a/b);} 17 } 18 */ 19 20 //n个方程m个未知量 21 int gauss(int n,int m){ 22 int r,c; 23 int num=0; //自由变元 24 for(r=0,c=0;r<n&&c<m;c++){ 25 int max_r=r; 26 for(int i=r+1;i<n;i++) if(abs(a[i][c]) > abs(a[max_r][c])) max_r=i; 27 if(max_r!=r) for(int j=c;j<=m;j++) swap(a[r][j],a[max_r][j]); 28 if(!a[r][c]) {free_x[num++]=c;continue;} // 29 for(int i=r+1;i<n;i++) if(a[i][c]){ 30 /* 31 int d=lcm(abs(a[i][c]),abs(a[r][c])); 32 int t1=d/a[i][c],t2=d/a[r][c]; 33 for(int j=c;j<=m;j++) a[i][j]=((a[i][j]*t1-a[r][j]*t2)%mod+mod)%mod; 34 */ 35 for(int j=c;j<=m;j++) a[i][j]^=a[r][j]; 36 } 37 r++; 38 } 39 for(int i=r;i<n;i++) if(a[i][m]) return -1; //无解 40 return num; //返回自由变元数 41 //求解 42 /* 43 for(int i=r-1;i>=0;i--){ 44 x[i]=a[i][m]; 45 for(int j=i+1;j<m;j++){ 46 x[i]=((x[i]-a[i][j]*x[j])%mod+mod)%mod; 47 } 48 int x1,y1,d; 49 exgcd(a[i][i],mod,d,x1,y1); 50 x1=((x1%mod)+mod)%mod; 51 x[i]=x[i]*x1%mod; 52 } 53 */ 54 55 //枚举自由变元(开关问题只能取0或1) 56 /* 57 int sta=1<<(m-r); 58 int res=inf; 59 for(int i=0;i<sta;i++){ 60 int cnt=0; 61 int id=i; 62 for(int j=0;j<num;j++){ 63 x[free_x[j]]=(id&1); 64 if(x[free_x[j]]) cnt++; 65 id>>=1; 66 } 67 for(int j=r-1;j>=0;j--){ 68 int temp=a[j][m]; 69 for(int k=j+i;k<m;k++){ 70 if(a[j][k]) temp^=x[k]; 71 } 72 x[j]=temp; 73 if(x[j]) cnt++; 74 } 75 if(cnt<res) res=cnt; 76 } 77 return res; 78 */ 79 }
1 const int maxn=75; 2 const int mod=131; //模数 3 int a[maxn][maxn]; 4 int x[maxn]; 5 6 int gcd(int a,int b){ 7 return b==0?a:gcd(b,a%b); 8 } 9 int lcm(int a,int b){ 10 return a/gcd(a,b)*b; 11 } 12 void exgcd(int a,int b,int &d,int &x,int &y){ 13 if(!b){d=a;x=1;y=0;} 14 else {exgcd(b,a%b,d,y,x); y-=x*(a/b);} 15 } 16 17 int gauss(int n,int m){ 18 int r,c; 19 for(r=0,c=0;r<n&&c<m;c++){ 20 int max_r=r; 21 for(int i=r+1;i<n;i++) if(abs(a[i][c]) > abs(a[max_r][c])) max_r=i; 22 if(max_r!=r) for(int j=c;j<=m;j++) swap(a[r][j],a[max_r][j]); 23 if(!a[r][c]) continue; 24 for(int i=r+1;i<n;i++) if(a[i][c]){ 25 int d=lcm(abs(a[i][c]),abs(a[r][c])); 26 int t1=d/a[i][c],t2=d/a[r][c]; 27 // if(a[i][c]*a[r][c]<0) t2=-t2; 28 for(int j=c;j<=m;j++) a[i][j]=((a[i][j]*t1-a[r][j]*t2)%mod+mod)%mod; 29 } 30 r++; 31 } 32 for(int i=r;i<n;i++) if(a[i][m]) return -1; //无解 33 for(int i=r-1;i>=0;i--){ 34 x[i]=a[i][m]; 35 for(int j=i+1;j<m;j++){ 36 x[i]=((x[i]-a[i][j]*x[j])%mod+mod)%mod; 37 } 38 int x1,y1,d; 39 exgcd(a[i][i],mod,d,x1,y1); 40 x1=((x1%mod)+mod)%mod; 41 x[i]=x[i]*x1%mod; 42 } 43 if(r<m) return m-r; //自由变元 44 return 1;//唯一解 45 }
1 const int inf=0x3f3f3f3f; 2 const int maxn=25; 3 int a[maxn][maxn]; 4 int x[maxn],free_x[maxn]; 5 int n,m; 6 7 int gauss(int n,int m){ 8 int r,c; 9 int num=0; 10 for(r=0,c=0;r<n&&c<m;c++){ 11 int max_r=r; 12 for(int i=r+1;i<n;i++) if(abs(a[i][c]) > abs(a[max_r][c])) max_r=i; 13 if(max_r!=r) for(int j=c;j<=m;j++) swap(a[r][j],a[max_r][j]); 14 if(!a[r][c]) {free_x[num++]=c;continue;} // 15 for(int i=r+1;i<n;i++) if(a[i][c]){ 16 for(int j=c;j<=m;j++) a[i][j]^=a[r][j]; 17 } 18 r++; 19 } 20 for(int i=r;i<n;i++) if(a[i][m]) return -1; 21 int sta=1<<(m-r); //方案数 22 int res=inf; 23 //枚举自由变元 24 for(int i=0;i<sta;i++){ 25 int cnt=0; 26 int id=i; 27 for(int j=0;j<m-r;j++){ 28 x[free_x[j]]=(id&1); 29 if(x[free_x[j]]) cnt++; 30 id>>=1; 31 } 32 for(int j=r-1;j>=0;j--){ 33 int temp=a[j][m]; 34 for(int k=j+1;k<m;k++){ 35 if(a[j][k]) temp^=x[k]; 36 } 37 x[j]=temp; 38 if(x[j]) cnt++; 39 } 40 if(cnt<res) res=cnt; 41 } 42 return res; 43 }
线性基
pow(1, 62) == 4 611 686 018 427 387 904
1 struct LiBase{ 2 ll a[63],p[63]; 3 int cnt; // 重建后,该线性基的范围是[1,1<<(cnt)-1] 4 //初始化 5 void init(){ 6 cnt=0; 7 memset(a,0,sizeof(a)); 8 memset(p,0,sizeof(p)); 9 } 10 //插入 11 bool insert_(ll x){ 12 for(int i=62;i>=0&&x;i--)if(x&(1LL<<i)){ 13 if(!a[i]){ 14 a[i]=x; 15 break; 16 }else x^=a[i]; 17 } 18 return x>0; 19 } 20 //最大 21 ll query_max(){ 22 ll ans=0; 23 for(int i=62;i>=0;i--){ 24 if((ans^a[i])>ans) ans^=a[i]; 25 } 26 return ans; 27 } 28 //最小 29 ll query_min(){ 30 for(int i=0;i<=62;i++) if(a[i]) return a[i]; 31 return 0; 32 } 33 //重建 34 void rebuid(){ 35 for(int i=62;i>=0;i--) 36 for(int j=i-1;j>=0;j--) if(a[i]&(1LL<<j)) a[i]^=a[j]; 37 for(int i=0;i<=62;i++) if(a[i]) p[cnt++]=a[i]; 38 } 39 //第k小 40 ll kth(ll k){ 41 ll ans=0; 42 if(k>=(1LL<<cnt)) return -1; 43 for(int i=cnt-1;i>=0;i--){ 44 if(k&(1LL<<i)) ans^=p[i]; 45 } 46 return ans; 47 } 48 }; 49 /* 50 合并 51 LiBase merge_(LiBase &x,LiBase &y){ 52 for(int i=60;i>=0;i--)if(y.a[i]) x.insert_(y.a[i]); 53 return x; 54 } 55 */
康拓展开(逆)
1 int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320}; //i的阶乘为fac[i] 2 // 康托展开-> 表示数字a是 a的全排列中从小到大排,排第几 3 // n表示1~n个数 a数组表示数字。 4 int kangtuo(int n, char a[]){ 5 int sum = 0; 6 for(int i = 0; i < n; i++){ 7 int t = 0; 8 for(int j = i + 1; j < n; j++) 9 if(a[i] > a[j]) t++; 10 sum += t * fac[n - i - 1]; 11 } 12 return sum+1; 13 } 14 15 //康托展开的逆运算,{1...n}的全排列,中的第k个数为s[] 16 void reverse_kangtuo(int n, int k, char s[]){ 17 int vis[8]={0}; 18 s[k] = 0; 19 --k; 20 for(int i = 0; i < n; i++){ 21 int t = k / fac[n - i - 1]; 22 int j; 23 for (j = 1; j <= n; j++){ 24 if (!vis[j]){ 25 if (t == 0) break; 26 --t; 27 } 28 } 29 s[i] = '0' + j; 30 vis[j] = 1; 31 k %= fac[n - i - 1]; 32 } 33 }