数学模板
素数打表
/*
语法:primetable(n,prime)
头文件:stdio.h string.h
参数:
m:求小于等于n的素数的个数中的n
prime:存素数的数组
返回值:null
*/
/*求小于等于n的素数的个数*/
int prime [ 100001 ]; //存素数
void primetable ( int n , int prime [])
{
int cnt = 0 ;
bool vis [ 100001 ]; //保证不做素数的倍数
memset ( vis , false , sizeof ( vis )); //初始化
memset ( prime , 0 , sizeof ( prime ));
for ( int i = 2 ; i <= n ; i ++ )
{
if ( ! vis [ i ]) //不是目前找到的素数的倍数
prime [ cnt ++ ] = i ; //找到素数~
for ( int j = 0 ; j < cnt && i * prime [ j ] <= n ; j ++ )
{
vis [ i * prime [ j ]] = true ; //找到的素数的倍数不访问
if ( i % prime [ j ] == 0 ) break ; //关键!!!!
}
}
printf ( "%d \n " , cnt );
}
求排列组合数
/*
语法: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 ;
}
行列式计算
/*
语法:result=js(int s[][],int n)
参数:
s[][]:行列式存储数组
n:行列式维数,递归用
返回值:行列式值
注意:函数中常数N为行列式维度,需自行定义
*/
int s [][ N ], n ;
int js ( s , n ) {
int z , j , k , r , total = 0 ;
int b [ N ][ N ];
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 ;
}
Ronberg算法计算积分
/*
语法:result=integral(double a,double b);
头文件:math.h
参数:
a:积分上限
b:积分下限
function f:积分函数
返回值:f在(a,b)之间的积分值
注意:
function f(x)需要自行修改,程序中用的是sina(x)/x
默认精度要求是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 ;
}
组合序列
/*
语法: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 ;
}
最大公约数、最小公倍数
/*
语法: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 );
}
任意进制转换
/*
语法: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 ;
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' ;
}
大数问题
大数阶乘
/*
语法:int result=factorial(int n);
头文件:math.h stdio.h
参数:
n:n 的阶乘
返回值:阶乘结果的位数
注意:
本程序直接输出n!的结果,需要返回结果请保留long a[]
*/
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 (( double ) a [ m ]) + 1 ;
printf ( "%ld" , a [ m ]);
for ( i = m -1 ; i >= 0 ; i -- ) printf ( "%4.4ld" , a [ i ]);
return w ;
}
大数加法
/*
语法:add(char a[],char b[],char s[]);
头文件:string.h
参数:
a[]:被加数,用字符串表示,位数不限
b[]:加数,用字符串表示,位数不限
s[]:结果,用字符串表示
返回值:null
注意:
空间复杂度为 o(n^2)
*/
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' ;
}
大数减法(未处理负数情况)
/*
语法:sub(char s1[],char s2[],char t[]);
头文件:string.h
参数:
s1[]:被减数,用字符串表示,位数不限
s2[]:减数,用字符串表示,位数不限
t[]:结果,用字符串表示
返回值:null
注意:
默认s1>=s2,程序未处理负数情况(倒过来加符号)
*/
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' ;}
}
大数乘法(大数乘小数)
/*
语法:mult(char c[],char t[],int m);
头文件:string.h
参数:
c[]:被乘数,用字符串表示,位数不限
t[]:结果,用字符串表示
m:乘数,限定10以内
返回值:null
*/
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' ;
}
大数乘法(大数乘大数)
/*
语法:mult(char a[],char b[],char s[]);
头文件:string.h
参数:
a[]:被乘数,用字符串表示,位数不限
b[]:乘数,用字符串表示,位数不限
t[]:结果,用字符串表示
返回值:null
注意:
空间复杂度为 o(n^2)
*/
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 ;
}
}
大数比较
/*
语法:int compare(char a[],char b[]);
参数:
a[]:被比较数,用字符串表示,位数不限
b[]:比较数,用字符串表示,位数不限
返回值:
0 a<b
1 a>b
2 a=b
*/
int compare ( char a [], char b [])
{
int lena = strlen ( a );
int lenb = strlen ( b );
if ( lena > lenb )
return 1 ;
else if ( lena < lenb )
return 0 ;
for ( int i = 0 ; i < lena ; i ++ )
{
if ( a [ i ] > b [ i ])
return 1 ;
else if ( a [ i ] < b [ i ])
return 0 ;
}
return 2 ;
}