ACM小组内部预定函数 数学问题:

 

ACM小组内部预定函数

Ver 2.0 by IcyFenix       

一、数学问题

1.精度计算——大数阶乘

语法:int result=factorial(int n);

参数:

n:

n 的阶乘

返回值:

阶乘结果的位数

注意:

 

 

本程序直接输出n!的结果,需要返回结果请保留long a[]

 

需要 math.h

源程序:

 

 

int factorial(int n)
{
long a[10000];
int i,j,l,c,m=0,w;

a[0]=1;
for(i=1;i<=n;i++)
    {
    c=0;
    
for(j=0;j<=m;j++)
        {
        a[j]=a[j]*i+c;
        c=a[j]/10000;
        a[j]=a[j]%10000;
    }
    
if(c>0) {m++;a[m]=c;}
}

w=m*4+log10(a[m])+1;
printf("/n%ld",a[m]);
for(i=m-1;i>=0;i--) printf("%4.4ld",a[i]);
return w;
}


2.精度计算——乘法(大数乘小数)

语法:mult(char c[],char t[],int m);

参数:

c[]:

被乘数,用字符串表示,位数不限

t[]:

结果,用字符串表示

m:

乘数,限定10以内

返回值:

null

注意:

 

 

需要 string.h

源程序:

 

 

void mult(char c[],char t[],int m)
{
    
int i,l,k,flag,add=0;
    
char s[100];
    l=strlen(c);
    
for (i=0;i<l;i++)
        s[l-i-1]=c[i]-'0';

    for (i=0;i<l;i++)
           {
           k=s[i]*m+add;
           
if (k>=10) {s[i]=k%10;add=k/10;flag=1;} else {s[i]=k;flag=0;add=0;}
           }
    
if (flag) {l=i+1;s[i]=add;} else l=i;

    for (i=0;i<l;i++)
        t[l-1-i]=s[i]+'0';
    t[l]='/0';
}

 

3.精度计算——乘法(大数乘大数)

语法:mult(char a[],char b[],char s[]);

参数:

a[]:

被乘数,用字符串表示,位数不限

b[]:

乘数,用字符串表示,位数不限

t[]:

结果,用字符串表示

返回值:

null

注意:

 

 

空间复杂度为 o(n^2)

 

需要 string.h

源程序:

 

 

void mult(char a[],char b[],char s[])
{
    
int i,j,k=0,alen,blen,sum=0,res[65][65]={0},flag=0;
    
char result[65];
    alen=strlen(a);blen=strlen(b);

    for (i=0;i<alen;i++)
    
for (j=0;j<blen;j++) res[i][j]=(a[i]-'0')*(b[j]-'0');

    for (i=alen-1;i>=0;i--)
        {
            
for (j=blen-1;j>=0;j--) sum=sum+res[i+blen-j-1][j];
            result[k]=sum%10;
            k=k+1;
            sum=sum/10;
        }

    for (i=blen-2;i>=0;i--)
        {
            
for (j=0;j<=i;j++) sum=sum+res[i-j][j];
            result[k]=sum%10;
            k=k+1;
            sum=sum/10;
        }
    
if (sum!=0) {result[k]=sum;k=k+1;}

    for (i=0;i<k;i++) result[i]+='0';
    
for (i=k-1;i>=0;i--) s[i]=result[k-1-i];
    s[k]='/0';

    while(1)
        {
        
if (strlen(s)!=strlen(a)&&s[0]=='0')
            strcpy(s,s+1);
        
else
            
break;
        }
}

 

4.精度计算——加法

语法:add(char a[],char b[],char s[]);

参数:

a[]:

被乘数,用字符串表示,位数不限

b[]:

乘数,用字符串表示,位数不限

t[]:

结果,用字符串表示

返回值:

null

注意:

 

 

空间复杂度为 o(n^2)

 

需要 string.h

源程序:

 

 

void add(char a[],char b[],char back[])
{
    
int i,j,k,up,x,y,z,l;
    
char *c;
    
if (strlen(a)>strlen(b)) l=strlen(a)+2; else l=strlen(b)+2;
    c=(
char *) malloc(l*sizeof(char));
    i=strlen(a)-1;
    j=strlen(b)-1;
    k=0;up=0;
    
while(i>=0||j>=0)
        {
            
if(i<0) x='0'; else x=a[i];
            
if(j<0) y='0'; else y=b[j];
            z=x-'0'+y-'0';
            
if(up) z+=1;
            
if(z>9) {up=1;z%=10;} else up=0;
            c[k++]=z+'0';
            i--;j--;
        }
    
if(up) c[k++]='1';
    i=0;
    c[k]='/0';
    
for(k-=1;k>=0;k--)
        back[i++]=c[k];
    back[i]='/0';
}

 

5.精度计算——减法

语法:sub(char s1[],char s2[],char t[]);

参数:

s1[]:

被减数,用字符串表示,位数不限

s2[]:

减数,用字符串表示,位数不限

t[]:

结果,用字符串表示

返回值:

null

注意:

 

 

默认s1>=s2,程序未处理负数情况

 

需要 string.h

源程序:

 

 

void sub(char s1[],char s2[],char t[])
{
    
int i,l2,l1,k;
    l2=strlen(s2);l1=strlen(s1);
    t[l1]='/0';l1--;
    
for (i=l2-1;i>=0;i--,l1--)
        {
        
if (s1[l1]-s2[i]>=0)
            t[l1]=s1[l1]-s2[i]+'0';
        
else
            {
            t[l1]=10+s1[l1]-s2[i]+'0';
            s1[l1-1]=s1[l1-1]-1;
            }
        }
    k=l1;
    
while(s1[k]<0) {s1[k]+=10;s1[k-1]-=1;k--;}
    
while(l1>=0) {t[l1]=s1[l1];l1--;}
loop:
    
if (t[0]=='0')
        {
        l1=strlen(s1);
        
for (i=0;i<l1-1;i++) t[i]=t[i+1];
        t[l1-1]='/0';
        goto loop;
        }
    
if (strlen(t)==0) {t[0]='0';t[1]='/0';}
}

 

6.任意进制转换

语法:conversion(char s1[],char s2[],long d1,long d2);

参数:

s[]:

原进制数字,用字符串表示

s2[]:

转换结果,用字符串表示

d1:

原进制数

d2:

需要转换到的进制数

返回值:

null

注意:

 

 

高于9的位数用大写'A'~'Z'表示,2~16位进制通过验证

源程序:

 

 

void conversion(char s[],char s2[],long d1,long d2)
{
    
long i,j,t,num;
    
char c;
    num=0;
    
for (i=0;s[i]!='/0';i++)
        {
        
if (s[i]<='9'&&s[i]>='0') t=s[i]-'0'; else t=s[i]-'A'+10;
        num=num*d1+t;
        }
    i=0;
    
while(1)
        {
        t=num%d2;
        
if (t<=9) s2[i]=t+'0'; else s2[i]=t+'A'-10;
        num/=d2;
        
if (num==0) break;
        i++;
        }
    
for (j=0;j<i/2;j++)
        {c=s2[j];s2[j]=s[i-j];s2[i-j]=c;}
    s2[i+1]='/0';
}

 

7.最大公约数、最小公倍数

语法:resulet=hcf(int a,int b)、result=lcd(int a,int b)

参数:

a:

int a,求最大公约数或最小公倍数

b:

int b,求最大公约数或最小公倍数

返回值:

返回最大公约数(hcf)或最小公倍数(lcd)

注意:

 

 

lcd 需要连同 hcf 使用

源程序:

 

 

int hcf(int a,int b)
{
    
int r=0;
    
while(b!=0)
        {
        r=a%b;
        a=b;
        b=r;
        }
    
return(a);
}

lcd(int u,int v,int h)
{
    
return(u*v/h);
}

 

8.组合序列

语法:m_of_n(int m, int n1, int m1, int* a, int head)

参数:

m:

组合数C的上参数

n1:

组合数C的下参数

m1:

组合数C的上参数,递归之用

*a:

1~n的整数序列数组

head:

头指针

返回值:

null

注意:

 

 

*a需要自行产生

 

初始调用时,m=m1、head=0

 

调用例子:求C(m,n)序列:m_of_n(m,n,m,a,0);

源程序:

 

 

void m_of_n(int m, int n1, int m1, int* a, int head)
{
    
int i,t;
    
if(m1<0 || m1>n1) return;

    if(m1==n1)
        {
        
for(i=0;i<m;i++) cout<<a[i]<<' '; // 输出序列
        cout<<'/n';
        
return;
        }
    m_of_n(m,n1-1,m1,a,head); // 递归调用
    t=a[head];a[head]=a[n1-1+head];a[n1-1+head]=t;
    m_of_n(m,n1-1,m1-1,a,head+1); // 再次递归调用
    t=a[head];a[head]=a[n1-1+head];a[n1-1+head]=t;
}

 

9.快速傅立叶变换(FFT)

语法:kkfft(double pr[],double pi[],int n,int k,double fr[],double fi[],int l,int il);

参数:

pr[n]:

输入的实部

pi[n]:

数入的虚部

n,k:

满足n=2^k

fr[n]:

输出的实部

fi[n]:

输出的虚部

l:

逻辑开关,0 FFT,1 ifFT

il:

逻辑开关,0 输出按实部/虚部;1 输出按模/幅角

返回值:

null

注意:

 

 

需要 math.h

源程序:

 

 

void kkfft(pr,pi,n,k,fr,fi,l,il)
int n,k,l,il;
double pr[],pi[],fr[],fi[];
{
    
int it,m,is,i,j,nv,l0;
    
double p,q,s,vr,vi,poddr,poddi;
    
for (it=0; it<=n-1; it++)
        {
         m=it; is=0;
        
for (i=0; i<=k-1; i++)
            {j=m/2; is=2*is+(m-2*j); m=j;}
        fr[it]=pr[is]; fi[it]=pi[is];
        }
    pr[0]=1.0; pi[0]=0.0;
    p=6.283185306/(1.0*n);
    pr[1]=cos(p); pi[1]=-sin(p);
    
if (l!=0) pi[1]=-pi[1];
    
for (i=2; i<=n-1; i++)
        {
       p=pr[i-1]*pr[1];
       q=pi[i-1]*pi[1];
        s=(pr[i-1]+pi[i-1])*(pr[1]+pi[1]);
        pr[i]=p-q; pi[i]=s-p-q;
        }
    
for (it=0; it<=n-2; it=it+2)
        {
       vr=fr[it]; vi=fi[it];
        fr[it]=vr+fr[it+1]; fi[it]=vi+fi[it+1];
        fr[it+1]=vr-fr[it+1]; fi[it+1]=vi-fi[it+1];
        }
    m=n/2; nv=2;
    
for (l0=k-2; l0>=0; l0--)
        {
        m=m/2; nv=2*nv;
        
for (it=0; it<=(m-1)*nv; it=it+nv)
            
for (j=0; j<=(nv/2)-1; j++)
                {
               p=pr[m*j]*fr[it+j+nv/2];
                q=pi[m*j]*fi[it+j+nv/2];
                s=pr[m*j]+pi[m*j];
                s=s*(fr[it+j+nv/2]+fi[it+j+nv/2]);
                poddr=p-q; poddi=s-p-q;
                fr[it+j+nv/2]=fr[it+j]-poddr;
                fi[it+j+nv/2]=fi[it+j]-poddi;
                fr[it+j]=fr[it+j]+poddr;
                fi[it+j]=fi[it+j]+poddi;
                }
        }
    
if (l!=0)
        
for (i=0; i<=n-1; i++)
            {
           fr[i]=fr[i]/(1.0*n);
            fi[i]=fi[i]/(1.0*n);
            }
    
if (il!=0)
            
for (i=0; i<=n-1; i++)
            {
           pr[i]=sqrt(fr[i]*fr[i]+fi[i]*fi[i]);
            
if (fabs(fr[i])<0.000001*fabs(fi[i]))
                {
              
if ((fi[i]*fr[i])>0) pi[i]=90.0;
                
else pi[i]=-90.0;
                }
            
else
                pi[i]=atan(fi[i]/fr[i])*360.0/6.283185306;
            }
    
return;
}

 

10.Ronberg算法计算积分

语法:result=integral(double a,double b);

参数:

a:

积分上限

b:

积分下限

function f:

积分函数

返回值:

f在(a,b)之间的积分值

注意:

 

 

function f(x)需要自行修改,程序中用的是sina(x)/x

 

需要 math.h

 

默认精度要求是1e-5

源程序:

 

 

double f(double x)
{
    
return sin(x)/x; //在这里插入被积函数
}

double integral(double a,double b)
{
    
double h=b-a;
    
double t1=(1+f(b))*h/2.0;
    
int k=1;
    
double r1,r2,s1,s2,c1,c2,t2;
loop:
    
double s=0.0;
    
double x=a+h/2.0;
    
while(x<b)
        {
        s+=f(x);
        x+=h;
        }
    t2=(t1+h*s)/2.0;
    s2=t2+(t2-t1)/3.0;
    
if(k==1)
      {
        k++;h/=2.0;t1=t2;s1=s2;
        goto loop;
        }
    c2=s2+(s2-s1)/15.0;
    
if(k==2){
        c1=c2;k++;h/=2.0;
        t1=t2;s1=s2;
        goto loop;
        }
    r2=c2+(c2-c1)/63.0;
    
if(k==3){
        r1=r2; c1=c2;k++;
        h/=2.0;
        t1=t2;s1=s2;
        goto loop;
        }
    
while(fabs(1-r1/r2)>1e-5){
        r1=r2;c1=c2;k++;
        h/=2.0;
        t1=t2;s1=s2;
        goto loop;
        }
    
return r2;
}

 

11.行列式计算

语法:result=js(int s[][],int n)

参数:

s[][]:

行列式存储数组

n:

行列式维数,递归用

返回值:

行列式值

注意:

 

 

函数中常数N为行列式维度,需自行定义

源程序:

 

 

int js(s,n)
int s[][N],n;
{
    
int z,j,k,r,total=0;
    
int b[N][N];/*b[N][N]用于存放,在矩阵s[N][N]中元素s[0]的余子式*/
    
if(n>2)
        {
       
for(z=0;z<n;z++)
            {
           
for(j=0;j<n-1;j++)
                 
for(k=0;k<n-1;k++)
                        
if(k>=z) b[j][k]=s[j+1][k+1];  else b[j][k]=s[j+1][k];
            
if(z%2==0) r=s[0][z]*js(b,n-1); /*递归调用*/
            
else r=(-1)*s[0][z]*js(b,n-1);
            total=total+r;
            }
        }
    
else if(n==2)
       total=s[0][0]*s[1][1]-s[0][1]*s[1][0];
    
return total;
}

 

12.求排列组合数

语法:result=P(long n,long m); / result=long C(long n,long m);

参数:

m:

排列组合的上系数

n:

排列组合的下系数

返回值:

排列组合数

注意:

 

 

符合数学规则:m<=n

源程序:

 

 

long P(long n,long m)
{
    
long p=1;
    
while(m!=0)
        {p*=n;n--;m--;}
    
return p;
}

long C(long n,long m)
{
    
long i,c=1;
    i=m;
    
while(i!=0)
        {c*=n;n--;i--;}
    
while(m!=0)
        {c/=m;m--;}
    
return c;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值