• *模板--数学


     

    加减乘除

      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
  • 相关阅读:
    微信小程序支付
    python中 try、except、finally执行顺序
    磁盘设备在 Linux 下的表示方法
    sanic中间件和监听器
    sed命令详解
    awk命令详解
    gd库
    php中计算二维数组中某一元素之和
    Linux SVN 命令详解
    PHP array 操作函数
  • 原文地址:https://www.cnblogs.com/yijiull/p/7236849.html
Copyright © 2020-2023  润新知