*模板--数学

 

加减乘除

  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 &quotient,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 }
String大数

 

 


 扩展欧几里得

 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 }
View Code

 


 

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

 

扩展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 }
扩展BSGS

 


 

 

欧拉函数(求与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 }
View Code

 


高斯消元

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

 

 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 */
View Code

 

 

康拓展开(逆)

 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 }
View Code

 

posted @ 2017-07-25 22:20  yijiull  阅读(188)  评论(0编辑  收藏  举报