zzuacm集训day1

来源:互联网 发布:mac系统 如何整理照片 编辑:程序博客网 时间:2024/04/30 00:44

1.归并排序

// 归并排序,时间O(logN)// 原数组为a数组 void merge( int l, int r){if ( l >= r)return; // 边界判断 int mid = ( l + r) / 2;// 递归处理 merge( l, mid);merge( mid + 1, r);int x, y;x = y = 0;// 左右两边放入辅助数组中 for ( int i = l; i <= mid; i++){ L[x++] = a[i]; }for ( int i = mid + 1; i <= r; i++){R[y++] = a[i];}L[x] = R[y] = 0x7f7f7f7f; // 哨兵 int j, k;j = k = 0;for ( int i = l; i <= r; i++){a[i] = L[j] < R[k] ? L[j++] : R[k++];// 回放到原数组 }}


另一种写法:

// 归并排序// 原始数组a, 辅助数组d void merge_sort( int l, int r){if ( l == r)return;int m = ( l + r) / 2;merge_sort( l, m);merge_sort( m + 1, r);int x = m - l + 1, y = r - m;int j, k, c;j = l, k = m + 1, c = 0;while ( j <= m && k <= r){if ( a[j] <= a[k]){d[c++] = a[j++];}else{d[c++] = a[k++];}}while ( j <= m){d[c++] = a[j++];}while ( k <= r){d[c++] = a[k++];}for ( int i = l; i <= r; i++){a[i] = d[i - l];}}



2.快排

// 快速排序(原址排序) void q_sort( int l, int r){if ( l >= r) // 边界处理 return;int c = a[l], i = l, j = r; // 选定值 while ( i < j){while ( i < j && a[j] >= c)j--;if ( i == j){a[i] = c;break;}a[i] = a[j];while ( i < j && a[i] <= c)i++;if ( i == j){a[i] = c;break;}a[j] = a[i];}// 递归处理 q_sort( l, i - 1);q_sort( i + 1, r);}

3.快速幂

// 快速幂 ll q_pow( ll a, ll b){ll ans = 1;while ( b){if ( b & 1)ans *= a;a *= a;b >>= 1;}return ans;} 


4.利用归并排序求逆序对个数

void merge_sort( int l, int r){if ( l == r)return;int m = ( l + r) / 2;merge_sort( l, m);merge_sort( m + 1, r);int x = m - l + 1, y = r - m;int j, k, t;j = l, k = m + 1, t = 0;while ( j <= m && k <= r){if ( a[j] <= a[k]){d[t] = a[j];b[t++] = a[j++];}else{c[k] += m - j + 1;d[t] = c[k];b[t++] = a[k++];}}while ( j <= m){d[t] = c[j];b[t++] = a[j++];}while ( k <= r){d[t] = c[k];b[t++] = a[k++];}for ( int i = l; i <= r; i++){a[i] = b[i - l];}}

5.手写大数

基本定义及读入、转化

#define maxn // 数字长度 #define base 10000int a[maxn / 4], b[maxn / 4]; // 保存以base为进制的数 char s1[maxn], s2[maxn]; // 用字符串保存原始数据 // 读入scanf( "%s%s", s1, s2);l1 = strlen( s1);l2 = strlen( s2);for ( j = 0, i = l1 - 1; i >= 3; j++, i -= 4){a[j] = s1[i] - '0' + 10 * ( s1[i - 1] - '0') + 100 * ( s1[i - 2] - '0')+ 1000 * ( s1[i - 3] - '0');} if ( i < 3){t = 0;multi = 1;for ( ; i >= 0; i--){t += multi * ( s1[i] - '0');multi *= 10;}a[j++] = t;}// s2处理与之一样,略掉 

运算

加法:

//加法, len1为a数组长度,len2为b数组长度 void add( int len1, int len2){for ( int i = 0; i < len2; i++){a[i] += b[i];a[i + 1] += a[i] / base;a[i] %= base;}a[len2 + 1] += a[len2] / base;a[len2] %= base;} 

除法:

// 除法,a为大数,n为普通数 ,len为a的长度 void div( int len, int n){for ( int i = len - 1, div = 0; i >= 0; i--){div = div * base + a[i];a[i] = div / n;div %= n;} } 
输出:

// 输出,大数a长度为len// 上述运算中并未考虑len的变化。。。 printf( "%d", a[len - 1]);for ( int i = len - 2; i >= 0; i--){printf( "%04d", a[i]);} putchar( '\n');


其实个人更加倾向于使用java大数,java大数不仅有整数还有实数,并且支持的操作也比较多

0 0