题目链接数制转换
题目大意:由a进制转换为b进制,其中(2<=a,b<=16)。
思路:将a数制先转换为10进制,然后10进制转换为b进制。
代码如下:
#include
#include
#include
#include
using namespace std;
const int MAX = 200;
vector<char> v;
void solve10tom(long long a, int m)//十进制转换为m进制
{
int b;
char t;
while(a)
{
b = a%m;
if(b>=10)
t = 'A'+b-10;
else
t = b+'0';
v.push_back(t);
a /= m;
}
for(int i=v.size()-1; i>=0; i--)
{
cout << v[i];
}
cout << endl;
v.clear();
}
long long solvemto10(char s[], int m)//m进制转换为10进制
{
long long p = 0, d = 0;
for(int i=0; i<strlen(s); i++)
{
if(s[i]>='a' && s[i]<='f')
d = 10+s[i]-'a';
else if(s[i]>='A' && s[i]<='F')
d = 10+s[i]-'A';
else
d = s[i]-'0';
p = p*m + d;
}
return p;
}
int main()
{
int a, b;
char s[MAX];
while(scanf("%d%s%d", &a, s, &b)!=EOF)
{
long long t = solvemto10(s, a);
if(t==0) cout << 0 << endl;
else solve10tom(t, b);
}
return 0;
}
题目链接进制转换
题目大意:30位的十进制数转换为二进制。
思路:难点是位数较多,只能存入数组,模仿手算的过程。
参考博文:九度OJ 1138 进制转换
代码如下:
#include
#include
using namespace std;
const int MAX = 200;
char s[MAX];
int input[MAX], output[MAX];
int main()
{
while(scanf("%s", s)!=EOF)
{
for(int i=0; i<strlen(s); i++)//将字符数组转换为数组
{
input[i] = s[i]-'0';
}
int k = 0, sum = 1, d, len = strlen(s);
while(sum)//当sum为0时代表计算已结束
{
sum = 0;
for(int i=0; i<len; i++)//遍历计算数组,从高位到低位
{
d = input[i]/2;//此位计算后的值,先存下
sum += d;//如果此位为0,则加0
if(i==len-1)//最后一位的决定余数
output[k++] = input[i]%2;
else//此位的余数可以在计算下一位的时候用的上
input[i+1] += (input[i]%2)*10;
input[i] = d;
}
}
if(!k) cout << 0 << endl;
else
{
for(int i=k-1; i>=0; i--)
cout << output[i];
cout << endl;
}
}
return 0;
}
我的代码:
#include
#include
#include
#include
using namespace std;
char s[50];
int main()
{
while(scanf("%s", s)!=EOF)
{
vector<int> v;//存储二进制结果
int st = 0, cnt, flag, len = strlen(s);
while(st<len)
{
cnt = 0, flag = 0;//cnt上一位的余数,flag标记是否可以移动st
for(int i=st; i<len; i++)
{
int a = (s[i]-'0'+cnt*10);//获取当前位
cnt = a%2;//余数
a /= 2;
s[i] = a+'0';
if(a!=0) flag = 1;
else if(!flag) st++;
}
v.push_back(cnt);
}
for(int i=v.size()-1; i>=0; i--)
printf("%d", v[i]);
printf("\n");
}
return 0;
}
题目链接质因数的个数
题目大意:输入一个正整数N(1
求素因数的的方法是,遍历区间内的所有素数,得到满足为因数的素数,一直用该正整数除以该因数,直到无法整除,继续遍历循环。如果遍历完区间后,该正整数仍然不为1,则加一即可。
方法一:直接求个数
代码如下:
#include
#include
#include
using namespace std;
const int MAX = 100001;
vector<int> v;
int a[MAX];
void checkPrime()
{
memset(a, 1, sizeof(a));
v.clear();
a[1] = 0;
for(int i=2; i<MAX; i++)
{
if(a[i])
{
for(int j=2*i; j<MAX; j+=i)
a[j] = 0;
v.push_back(i);
}
}
}
int solve(int n)
{
int i=0, sum = 0;
while(i<v.size())
{
while(n%v[i]==0)
{
n/=v[i];
sum++;
}
i++;
}
if(n!=1) sum++;
return sum;
}
int main()
{
int N;
checkPrime();
while(cin >> N)
{
cout << solve(N) << endl;
}
return 0;
}
方法二:保存质因数和其幂数。
代码如下:
#include
using namespace std;
const int MAX = 100001;
bool mark[MAX];
int prime[MAX];
int primeSize;
void init()
{
primeSize = 0;
for(int i=2; i<MAX; i++)
{
if(mark[i]) continue;
prime[primeSize++] = i;
if(i>=1000) continue;
for(int j=i*i; j<=MAX; j+=i)
mark[j] = true;
}
}
int main()
{
init();
int n;
while(cin >> n)
{
int ansPrime[30];
int ansSize = 0;
int ansNum[30];
for(int i=0; i<primeSize; i++)
{
if(n%prime[i]==0)
{
ansPrime[ansSize] = prime[i];
ansNum[ansSize] = 0;
while(n%prime[i]==0)
{
ansNum[ansSize]++;
n/=prime[i];
}
ansSize++;
if(n==1) break;
}
}
if(n!=1)
{
ansPrime[ansSize] = n;
ansNum[ansSize++] = 1;
}
int ans = 0;
for(int i=0; i<ansSize; i++)
{
ans += ansNum[i];
}
cout << ans << endl;
}
return 0;
}
题目链接整除问题
思路参考《王道计算机考研机试指南》第83页。
以下是我根据其思路写的代码,可以通过,不过比着书上的代码繁杂了一些。
#include
#include
#include
#include
using namespace std;
const int MAX = 1001;
bool mark[MAX];
int prime[MAX];
int primeSize;
void init()
{
primeSize = 0;
memset(mark, false, sizeof(mark));
for(int i=2; i<MAX; i++)
{
if(mark[i]) continue;
prime[primeSize++] = i;
//if(i>=1000) continue;
for(int j=i*i; j<=MAX; j+=i)
mark[j] = true;
}
}
int main()
{
int n, a;
init();
vector<int> ansPrimen, ansPrimea;
vector<int> cntn, cnta;
while(cin >> n >> a)
{
ansPrimen.clear();
ansPrimea.clear();
cntn.clear();
cnta.clear();
for(int i=0; i<primeSize; i++)
{
if(n<prime[i] && a==1) break;
if(n>=prime[i])
{
int t = 1, sumn = 0;
while(n/pow(prime[i], t))//求n!的素因数
{
sumn += n/pow(prime[i], t);
t++;
}
ansPrimen.push_back(prime[i]);
cntn.push_back(sumn);
}
if(a%prime[i]==0 && a!=1)//求a的素因数
{
int suma = 0;
while(a%prime[i]==0)
{
suma++;
a/=prime[i];
}
ansPrimea.push_back(prime[i]);
cnta.push_back(suma);
}
}
int j = 0, k = MAX;
for(int i=0; i<ansPrimea.size(); i++)
{
while(ansPrimea[i]!=ansPrimen[j]) j++;
k = min(k, cntn[j]/cnta[i]);
}
cout << k << endl;
}
return 0;
}
代码2:
#include
#include
#include
#include
#include
using namespace std;
const int MAX = 1005;
int isPrime[MAX], prime1[MAX], prime2[MAX], e1[MAX], e2[MAX];
void checkPrime()
{
fill(isPrime, isPrime+MAX, 1);
isPrime[0] = 0, isPrime[1] = 0;
for(int i=2; i<=sqrt(MAX+0.5); i++)
{
if(!isPrime[i]) continue;
for(int j=2*i; j<=MAX; j+=i)
{
isPrime[j] = 0;
}
}
}
int main()
{
int n, a;
checkPrime();
scanf("%d%d", &n, &a);
memset(e1, 0, sizeof(e1));
memset(e2, 0, sizeof(e2));
//获取n!的因数因数分解
for(int i=2; i<=n; i++)
{
int cnt = i;
if(isPrime[cnt])
{
e1[cnt]++;
continue;
}
for(int j=2; j<=n; j++)
{
if(j>cnt) break;
if(!isPrime[j]) continue;
while(cnt%j==0)
{
cnt /= j;
e1[j]++;
}
}
if(cnt!=1) e1[cnt]++;
}
//获取a的因数分解
int cnt = a;
for(int j=2; j<=a; j++)
{
if(j>cnt) break;
if(!isPrime[j]) continue;
while(cnt%j==0)
{
cnt /= j;
e2[j]++;
}
}
if(cnt!=1) e2[cnt]++;
//根据指数比较出k
int k = 1<<29;
for(int i=2; i<=a; i++)
{
if(!isPrime[i] || e2[i]==0) continue;
if(e1[i]>=e2[i])//必须保证e2[i]!=0
{
k = min(k, e1[i]-e2[i]+1);
}
else//说明n!不是a的倍数
{
k = 0;
break;
}
}
printf("%d\n", k);
return 0;
}
题目链接约数的个数
题目大意:给出正整数(1质数的个数
一题的思想可以将其转化为sqrt(n)的范围。
代码如下:
#include
#include
using namespace std;
const int MAX = 10000001;
int a[MAX];
int main()
{
int n;
while(cin >> n && n)
{
for(int i=0; i<n; i++)
cin >> a[i];
for(int i=0; i<n; i++)
{
int sum = 0;
if(a[i]==1)
{
cout << 1 << endl;
continue;
}
int t = sqrt(a[i]);//默认向下取整
if(t*t==a[i]) sum--;
for(int j=1; j<=t; j++)
{
if(a[i]%j==0) sum+=2;
}
cout << sum << endl;
}
}
return 0;
}
题目链接人见人爱A^B
题目大意:求A^B(1<=A,B<=10000)
思路:可以跟二进制联系在一起,也可以跟奇偶性联系在一起。
代码如下
#include
using namespace std;
typedef long long LL;
const int MAX = 1000;
LL Power(LL m, LL n)
{
LL res = 1;
while(n>0)
{
if(n&1) res = res*m%MAX;//n为奇数时将上一次计算的值乘起来
m = m*m%MAX;
n >>= 1;//n除以2
}
return res;
}
int main()
{
LL m, n;
while(cin >> m >> n && (m+n))
{
LL res = Power(m, n);
cout << res << endl;
}
return 0;
}
题目链接Tr A
题目大意:求矩阵A的迹的K此幂的迹元素之和。K(2 <= K < 10^9)
思路:此题为矩阵快速幂的模板题。
参考博客矩阵快速幂(原理+模板)
代码如下:
#include
#include
using namespace std;
typedef long long LL;
const int mod = 9973;
struct Mat//矩阵结构体
{
int a[11][11];
};
Mat M;
Mat mul(Mat A, Mat B, LL m)//矩阵乘法
{
Mat C;
for(int i=0; i<m; i++)//初始化
{
for(int j=0; j<m; j++)
{
C.a[i][j] = 0;
}
}
for(int i=0; i<m; i++)
{
for(int j=0; j<m; j++)
{
for(int k=0; k<m; k++)
{
C.a[i][j] = C.a[i][j]%mod+A.a[i][k]*B.a[k][j]%mod;
}
}
}
return C;
}
Mat Pow(Mat M, LL p, LL m)//矩阵快速幂模板
{
Mat res;
for(int i=0; i<m; i++)//初始化为单位矩阵,单位矩阵乘以任何矩阵不变
{
for(int j=0; j<m; j++)
{
if(i==j)
res.a[i][j] = 1;
else
res.a[i][j] = 0;
}
}
while(p)//类似二分求幂
{
if(p&1) res = mul(res, M, m);
M = mul(M, M, m);
p >>= 1;
}
return res;
}
int main()
{
LL n, m, p;
cin >> n;
while(n--)
{
cin >> m >> p;
for(int i=0; i<m; i++)
{
for(int j=0; j<m; j++)
{
cin >> M.a[i][j];
}
}
Mat res = Pow(M, p, m);
int sum = 0;
for(int i=0; i<m; i++) sum += res.a[i][i];//求迹和
cout << sum%mod << endl;
}
return 0;
}
题目链接a+b
方法一:建立一个大整数的结构体
代码如下:
#include
#include
#include
using namespace std;
const int MAX = 1001;
struct bigInteger
{
int digit[MAX];
int size;
void init()
{
for(int i=0; i<MAX; i++) digit[i] = 0;
size = 0;
}
void set(char str[])
{
init();
int L = strlen(str);
for(int i=L-1, j=0, t=0, c=1; i>=0; i--)//j控制没4个字符转换为一个数字存入数组,t临时保存字符转换为数字的中间值,c表示当前为的权重,按1,10,100,1000顺序变化
{
t += (str[i]-'0')*c;//计算这个四位数中当前字符代表的数字,即数字乘以当前位权重
j++;//当前字符数增加
c *= 10;//计算下一位权重
if(j==4 || i==0)//若已经连续转换4个字符,或者已经到达最后一个字符
{
digit[size++] = t;
j = 0;
t = 0;
c = 1;
}
}
}
void output()
{
for(int i=size-1; i>=0; i--)
{
if(i!=size-1) printf("%04d", digit[i]);
else printf("%d", digit[i]);
}
printf("\n");
}
bigInteger operator + (const bigInteger &A) const
{
bigInteger ret;
ret.init();
int carry = 0;
for(int i=0; i<A.size || i<size; i++)
{
int tmp = A.digit[i]+digit[i]+carry;
carry = tmp/10000;
tmp %= 10000;
ret.digit[ret.size++] = tmp;
}
if(carry!=0) ret.digit[ret.size++] = carry;
return ret;
}
}a, b, c;
int main()
{
char str1[MAX], str2[MAX];
while(scanf("%s%s", str1, str2)!=EOF)
{
a.set(str1);
b.set(str2);
c = a+b;
c.output();
}
return 0;
}
方法二:自己写的,直接函数实现,不如方法一规范。
#include
#include
#include
#include
using namespace std;
const int MAX = 1001;
struct bigInteger
{
int digit[MAX];
int sized;
};
bigInteger str2num(char s[])
{
bigInteger B;
memset(B.digit, 0, sizeof(B.digit));
int k = 0, i;
for(i=strlen(s)-1; i>=0; i-=4)
{
if(i-3<0)
{
break;
}
for(int j=i-3; j<=i; j++)
{
B.digit[k] = B.digit[k]*10+s[j]-'0';
}
k++;
}
if(i>=0)
{
for(int j=0; j<=i; j++)
{
B.digit[k] = B.digit[k]*10+s[j]-'0';
}
k++;
}
B.sized = k;
return B;
}
bigInteger add(bigInteger a, bigInteger b)
{
int L = max(a.sized, b.sized), m = 0;
if(a.sized<b.sized) swap(a, b);
for(int i=0; i<L; i++)
{
int t = a.digit[i]+b.digit[i]+m;
if(t<10000)
{
a.digit[i] = t;
m = 0;
}
else
{
a.digit[i] = t%10000;
m = 1;
}
}
if(m)
{
a.digit[L] = a.digit[L]+1;
a.sized++;
}
return a;
}
int Pow(int a, int b)
{
int c = 1;
for(int i=0; i<b; i++)
{
c *= a;
}
return c;
}
int main()
{
char s1[MAX], s2[MAX];
while(scanf("%s%s", s1, s2)!=EOF)
{
bigInteger a = str2num(s1);
bigInteger b = str2num(s2);
bigInteger c = add(a, b);
for(int i=c.sized-1; i>=0; i--)
{
if(i==c.sized-1)
{
cout << c.digit[i];
continue;
}
int k = 3, t = c.digit[i];
while(k>=0)
{
cout << t/Pow(10, k);
t = t%Pow(10, k);
k--;
}
}
cout << endl;
}
return 0;
}
方法三:(实用string的简单实现方法)
#include
#include
#include
#include
#include
using namespace std;
string add(string a, string b)
{
string c = "";//存储结果
int lena = a.size(), lenb = b.size();
int cnta = lena-1, cntb = lenb-1, pre = 0;//cnta,cntb是下标,pre是进位
int ai, bi, ci;
while(cnta>=0 || cntb>=0)
{
if(cnta>=0) ai = a[cnta]-'0';
else ai = 0;
if(cntb>=0) bi = b[cntb]-'0';
else bi = 0;
ci = ai+bi+pre;
pre = ci/10;
ci = ci%10;
c = char(ci+'0')+c;
cnta--, cntb--;
}
if(pre) c = char(pre+'0')+c;//不要忘记最后检查一下
return c;
}
int main()
{
string a, b;
while(cin >> a >> b)
{
cout << add(a, b) << endl;
}
return 0;
}
题目链接进制转换
手动进制转换,以10进制为中介。
代码如下:
#include
#include
#include
using namespace std;
const int MAX = 1001;
struct bigInteger
{
int digit[MAX];
int size;
void init()
{
memset(digit, 0, sizeof(digit));
size = 0;
}
void set(char str[])
{
init();
int L = strlen(str);
for(int i=L-1, j=0, t=0, c = 1; i>=0; i--)
{
t += (str[i]-'0')*c;
j++;
c *= 10;
if(j==4 || i==0)
{
digit[size++] = t;
j = 0;
t = 0;
c = 1;
}
}
}
void output()
{
for(int i=size-1; i>=0; i--)
{
if(i!=size-1) printf("%04d", digit[i]);
else printf("%d", digit[i]);
}
printf("\n");
}
bigInteger operator * (const int &x) const
{
bigInteger ret;
ret.init();
int carry = 0;
for(int i=0; i<size; i++)
{
int tmp = digit[i]*x+carry;
ret.digit[ret.size++] = tmp%10000;
carry = tmp/10000;
}
if(carry!=0) ret.digit[ret.size++] = carry;
return ret;
}
bigInteger operator + (const bigInteger &A) const
{
bigInteger ret;
ret.init();
int carry = 0;
for(int i=0; i<size; i++)
{
int tmp = digit[i]+A.digit[i]+carry;
ret.digit[ret.size++] = tmp%10000;
carry = tmp/10000;
}
if(carry!=0) ret.digit[ret.size++] = carry;
return ret;
}
bigInteger operator / (const int &x) const
{
bigInteger ret;
ret.init();
int carry = 0, flag = 0;
for(int i=size-1; i>=0; i--)
{
ret.digit[i] = (digit[i]+carry*10000)/x;
carry = (digit[i]+carry*10000)%x;
if(ret.digit[i]!=0 && flag==0)
{
ret.size = i;
flag = 1;
}
}
ret.size++;
return ret;
}
int operator % (const int &x) const
{
int carry = 0;
for(int i=size-1; i>=0; i--)
{
carry = (digit[i]+carry*10000)%x;
}
return carry;
}
};
char str[MAX], ans[MAX];
bigInteger a, b, c;
int main()
{
int M, N, X;
while(scanf("%d%d", &M, &N)!=EOF)
{
scanf("%s", str);
a.set("0");
b.set("1");
int t;
for(int i=strlen(str)-1; i>=0; i--)//得到转化为10进制的数字
{
if(str[i]>='0' && str[i]<='9') t = str[i]-'0';
else t = str[i]-'A'+10;
a = b*t+a;//注意没有定义符号的优先级和括号
b = b*M;
}
int k = 0;
if(N!=10)
{
do
{
//cout << a.size << endl;
t = a%N;
a = a/N;
if(t>=10) ans[k++] = t-10+'a';
else ans[k++] = t+'0';
}while(a.size!=1 || a.digit[0]!=0);
for(int i=k-1; i>=0; i--)
{
cout << ans[i];
}
cout << endl;
}
else
a.output();
}
return 0;
}
题目链接10进制vs2进制
思路:结构体及其内置函数与上题进制转换
一样,就是主函数操作不一样。均是手动进制转换。
代码如下:
#include
#include
#include
#include
using namespace std;
const int MAX = 1001;
const int M = 1<<29;
struct bigInteger
{
int digit[MAX];
int size;
void init()
{
memset(digit, 0, sizeof(digit));
size = 0;
}
void set(char str[])
{
init();
int L = strlen(str);
for(int i=L-1, j=0, t=0, c = 1; i>=0; i--)
{
t += (str[i]-'0')*c;
j++;
c *= 10;
if(j==4 || i==0)
{
digit[size++] = t;
j = 0;
t = 0;
c = 1;
}
}
}
void output()
{
for(int i=size-1; i>=0; i--)
{
if(i!=size-1) printf("%04d", digit[i]);
else printf("%d", digit[i]);
}
printf("\n");
}
bigInteger operator * (const int &x) const
{
bigInteger ret;
ret.init();
int carry = 0;
if(x==0) return ret;//乘以0,则为0
for(int i=0; i<size; i++)
{
int tmp = digit[i]*x+carry;
ret.digit[ret.size++] = tmp%10000;
carry = tmp/10000;
}
if(carry!=0) ret.digit[ret.size++] = carry;
return ret;
}
bigInteger operator + (const bigInteger &A) const
{
bigInteger ret;
ret.init();
int carry = 0;
int L = max(size, A.size);
for(int i=0; i<L; i++)
{
//if(i==L-1 && digit[i]==0 && A.digit[i]==0) break;
int tmp = digit[i]+A.digit[i]+carry;
ret.digit[ret.size++] = tmp%10000;
carry = tmp/10000;
}
if(carry!=0) ret.digit[ret.size++] = carry;
return ret;
}
bigInteger operator / (const int &x) const
{
bigInteger ret;
ret.init();
int carry = 0, flag = 0;
for(int i=size-1; i>=0; i--)
{
ret.digit[i] = (digit[i]+carry*10000)/x;
carry = (digit[i]+carry*10000)%x;
if(ret.digit[i]!=0 && flag==0)
{
ret.size = i;
flag = 1;
}
}
ret.size++;
return ret;
}
int operator % (const int &x) const
{
int carry = 0;
for(int i=size-1; i>=0; i--)
{
carry = (digit[i]+carry*10000)%x;
}
return carry;
}
};
char str[MAX], ans[M];
bigInteger a, b, c;
int main()
{
while(scanf("%s", str)!=EOF)
{
a.set(str);
//a.output();
b.set("0");
c.set("1");
int t, k = 0;
while(a.size!=1 || a.digit[0]!=0)//a的值为0时跳出
{
t = a%2;
a = a/2;
ans[k++] = t+'0';
}
for(int i=k-1; i>=0; i--)
{
t = ans[i]-'0';
b = c*t+b;
c = c*2;
}
b.output();
}
return 0;
}
题目链接浮点加法
需要考虑整数和小数两种大整数的运算。
方法一:思想是分成两部分(整数和小数)相加,然后其中整数部分数组低下标处为低位,小数部分低下标处为高位。先算小数相加(有向整数的进位),从高下标向低下标遍历相加,整数部分相反方向遍历相加,其中有变量存着进位。
参考博客浮点数加法 九度oj
代码如下:
#include
#include
#include
#define LEN 101
int ia[LEN], fa[LEN], ib[LEN], fb[LEN], ic[LEN], fc[LEN];
int main()
{
char str1[LEN], str2[LEN];
int i, j, k, n, l1, l2, lai, laf, lbi, lbf, temp, flmax, ilmax;
while (scanf("%d", &n) != EOF) {
while (n --) {
// 初始化
memset(ia, 0, sizeof(ia));
memset(fa, 0, sizeof(fa));
memset(ib, 0, sizeof(ib));
memset(fb, 0, sizeof(fb));
memset(ic, 0, sizeof(ic));
memset(fc, 0, sizeof(fc));
// 接收第一个浮点数
scanf("%s", str1);
l1 = strlen(str1);
// 构建整数部分数组
for (i = 0; i < l1 && str1[i] != '.'; i ++) {
ia[i] = str1[i] - '0';
}
lai = i;
// 数位替换
for (j = 0, k = lai - 1; j <= lai / 2 && j < k; j ++, k --) {
temp = ia[j];
ia[j] = ia[k];
ia[k] = temp;
}
// 构建小数部分数组
for (i += 1; i < l1; i ++) {
fa[i - 1 - lai] = str1[i] - '0';
}
laf = i - 1 - lai;
// 接收第二个浮点数
scanf("%s", str2);
l2 = strlen(str2);
// 构建整数部分数组
for (i = 0; i < l2 && str2[i] != '.'; i ++) {
ib[i] = str2[i] - '0';
}
lbi = i;
// 数位替换
for (j = 0, k = lbi - 1; j <= lbi / 2 && j < k; j ++, k --) {
temp = ib[j];
ib[j] = ib[k];
ib[k] = temp;
}
// 构建小数部分数组
for (i += 1; i < l2; i ++) {
fb[i - 1 - lbi] = str2[i] - '0';
}
lbf = i - 1 - lbi;
// 谁的小数位数更多
flmax = (laf >= lbf) ? laf : lbf;
int c = 0; //小数进位
for (i = 0, j = flmax - 1; j >= 0; j --, i ++) {
fc[i] = fa[j] + fb[j] + c;
if (fc[i] >= 10) {
c = fc[i] / 10;
fc[i] %= 10;
}else {
c = 0;
}
}
// 整数相加
ilmax = (lai >= lbi) ? lai : lbi;
for (i = 0; i < ilmax; i ++) {
ic[i] = ia[i] + ib[i] + c;
if (ic[i] >= 10) {
c = ic[i] / 10;
ic[i] %= 10;
}else {
c = 0;
}
}
while (c) {
ic[ilmax ++] = c % 10;
c /= 10;
}
// 打印最后结果
// 找到第一个不为0的整数位
for (j = ilmax - 1; j >= 0; j --) {
if (ic[j] != 0) {
break;
}
}
if (j >= 0) {
for (i = j; i >= 0; i --) {
printf("%d", ic[i]);
}
}else {
printf("0");
}
printf(".");
// 找到最后一个不为0的小数位
for (j = 0; j < flmax - 1; j ++) {
if (fc[j] != 0) {
break;
}
}
for (i = flmax - 1; i >= j; i --) {
printf("%d", fc[i]);
}
printf("\n");
// 接收空行
getchar();
}
}
return 0;
}
/************************************************************** Problem: 1137 User: wangzhengyi Language: C Result: Accepted Time:290 ms Memory:912 kb ****************************************************************/
方法二:
自己写的,按照给出的bigInteger结构体,将小数和整数部分均用结构体存储,然后操作的时候再手动浮点相加,写的不太好,但写了4、5个小时,总算过了,记录一下吧。
代码如下:
#include
#include
#include
using namespace std;
const int MAX = 1001;
char s1[MAX], s2[MAX];
struct bigInteger
{
int digit[MAX];
int size;
void init()
{
memset(digit, 0, sizeof(digit));
size = 0;
}
void set(char str[])
{
init();
int L = strlen(str);
for(int i=L-1, j=0, t=0, c = 1; i>=0; i--)
{
t += (str[i]-'0')*c;
j++;
c *= 10;
if(j==4 || i==0)
{
digit[size++] = t;
j = 0;
t = 0;
c = 1;
}
}
}
void output()
{
for(int i=size-1; i>=0; i--)
{
if(i!=size-1) printf("%04d", digit[i]);
else printf("%d", digit[i]);
}
//printf("\n");
}
bigInteger operator + (const bigInteger &A) const
{
bigInteger ret;
ret.init();
int carry = 0;
for(int i=0; i<A.size || i<size; i++)
{
int tmp = A.digit[i]+digit[i]+carry;
carry = tmp/10000;
tmp %= 10000;
ret.digit[ret.size++] = tmp;
}
if(carry!=0) ret.digit[ret.size++] = carry;
return ret;
}
};
struct Node
{
char str[2][MAX];
};
struct bigFloat
{
bigInteger F[2];
void init()
{
F[0].init();
F[1].init();
}
};
Node split(char s[], char t)
{
//memset(str1, "", sizeof(str1));
//memset(str2, "", sizeof(str2));
Node S;
memset(S.str, 0, sizeof(S.str));
//S.init();
int flag = 0, L = strlen(s), ind = 0;
//cout << L << endl;
for(int i=0; i<L; i++)
{
if(s[i]==t)
{
flag = 1;
ind = i;
continue;
}
if(flag)
{
S.str[1][i-ind-1] = s[i];
}
else
{
S.str[0][i] = s[i];
}
}
return S;
}
int len(bigInteger a)
{
int L = (a.size-1)*4;
int t = a.digit[a.size-1];
while(t)
{
t /= 10;
L++;
}
return L;
}
int main()
{
Node str1, str2;
bigFloat f1, f2;
bigInteger inter, floa, carry;
while(scanf("%s%s", s1, s2)!=EOF)
{
inter.init();
floa.init();
carry.init();
f1.init();
f2.init();
str1 = split(s1, '.');
str2 = split(s2, '.');
while(strlen(str2.str[1])<strlen(str1.str[1]))
{
strcat(str2.str[1], "0");
}
while(strlen(str2.str[1])>strlen(str1.str[1]))
{
strcat(str1.str[1], "0");
}
f1.F[0].set(str1.str[0]);
f1.F[1].set(str1.str[1]);
f2.F[0].set(str2.str[0]);
f2.F[1].set(str2.str[1]);
floa = f1.F[1]+f2.F[1];
char p[MAX] = {'1'};
int L1 = max(len(f1.F[1]), len(f2.F[1]));
if(len(floa)>L1)
{
//cout << endl;
if(len(floa)%4==1) floa.size--;
else
{
int t = floa.digit[floa.size-1], L = 1;
while(t)
{
t/=10;
L *= 10;
}
L /= 10;
floa.digit[floa.size-1] %= L;
}
//sprintf(p, "%d", t);
carry.set(p);
}
inter = f1.F[0]+f2.F[0];
inter = inter+carry;
inter.output();
printf(".");
if(len(floa)<L1) cout << 0;
floa.output();
//cout << str1.str[0][0] << endl;
}
return 0;
}
后来我变强一些之后又写了一次,用例大概半个小时调试AC了,方法更精炼一些。
#include
#include
#include
#include
#include
using namespace std;
string add(string a, string b, int p)
{
string c = "";//存储结果
int lena = a.size(), lenb = b.size();
int cnta = lena-1, cntb = lenb-1, pre = p;//cnta,cntb是下标,pre是进位
int ai, bi, ci;
while(cnta>=0 || cntb>=0)
{
if(cnta>=0) ai = a[cnta]-'0';
else ai = 0;
if(cntb>=0) bi = b[cntb]-'0';
else bi = 0;
ci = ai+bi+pre;
pre = ci/10;
ci = ci%10;
c = char(ci+'0')+c;
cnta--, cntb--;
}
if(pre) c = char(pre+'0')+c;//不要忘记最后检查一下
return c;
}
string add2(string a, string b, int p)
{
string c = "";//存储结果
if(a.size()<b.size()) swap(a, b);
int lena = a.size(), lenb = b.size();
for(int i=lena-1; i>=lenb; i--)//实现将超出的位赋值
c = a[i]+c;
int cnta = lenb-1, cntb = lenb-1, pre = p;//cnta,cntb是下标,pre是进位
int ai, bi, ci;
while(cnta>=0 || cntb>=0)
{
if(cnta>=0) ai = a[cnta]-'0';
else ai = 0;
if(cntb>=0) bi = b[cntb]-'0';
else bi = 0;
ci = ai+bi+pre;
pre = ci/10;
ci = ci%10;
c = char(ci+'0')+c;
cnta--, cntb--;
}
if(pre) c = char(pre+'0')+c;//不要忘记最后检查一下
return c;
}
int main()
{
string a, b, a1, a2, b1, b2;
while(cin >> a >> b)
{
int p = 0;
int pa = a.find('.', 0);
int pb = b.find('.', 0);
if(pa<a.size() && pa>=0)//有小数位
a1 = a.substr(0, pa), a2 = a.substr(pa+1, a.size()-pa);
else//没有小数位
a1 = a, a2 = "0";
if(pb<b.size() && pb>=0)
b1 = b.substr(0, pb), b2 = b.substr(pb+1, b.size()-pb);
else
b1 = b, b2 = "0";
string c2 = add2(a2, b2, p);//小数位相加
if(c2.size()>max(a2.size(), b2.size()))//如果小数位向整数位有进位
{
p = 1;
c2.erase(0, 1);
}
string c1 = add(a1, b1, p);//整数位相加
if(c2=="0")//如果结果没有小数位
cout << c1 << endl;
else
cout << c1 << "." << c2 << endl;
}
return 0;
}
题目链接大整数排序
思路:自定义大整数的小于<符号,然后实现一个冒泡排序的函数即可。
PS:发现我之前的思路好傻,直接使用string字符串模拟大整数就可以了(string类型自带比较级),只不过当长度不同时,长度长的一定大,长度相同时,比较字符串大小即可。
string方法的代码:
#include
#include
#include
#include
#include
using namespace std;
struct BigInter
{
string s;
bool operator < (const BigInter &A) const
{
if(A.s.size()!=s.size())
return s.size()<A.s.size();
else
return s<A.s;
}
};
BigInter B[105];
int main()
{
int N;
cin >> N;
for(int i=0; i<N; i++)
cin >> B[i].s;
sort(B, B+N);
for(int i=0; i<N; i++)
cout << B[i].s << endl;
return 0;
}
代码如下:
#include
#include
using namespace std;
const int MAX = 1001;
struct bigInteger
{
int digit[MAX];
int size;
void init()
{
memset(digit, 0, sizeof(digit));
size = 0;
}
void set(char str[])
{
init();
int L = strlen(str);
for(int i=L-1, j=0, t=0, c = 1; i>=0; i--)
{
t += (str[i]-'0')*c;
j++;
c *= 10;
if(j==4 || i==0)
{
digit[size++] = t;
j = 0;
t = 0;
c = 1;
}
}
}
void output()
{
for(int i=size-1; i>=0; i--)
{
if(i!=size-1) printf("%04d", digit[i]);
else printf("%d", digit[i]);
}
printf("\n");
}
bool operator < (const bigInteger &x) const//自定义小于符号
{
//cout << size << " " << x.size << endl;
//cout << size-x.size << endl;
if(size-x.size==0)
{
//cout << 4 << endl;
for(int i=size-1; i>=0; i--)
{
if(digit[i]!=x.digit[i])
return digit[i]<x.digit[i];
}
}
else
return size<x.size;
//cout << 3 << endl;
return 0;
}
};
void bigIntegerSort(bigInteger ret[], int n)
{
for(int i=n-1; i>=0; i--)//简单的冒泡排序
{
for(int j=n-1; j>=n-i; j--)
{
if(ret[j]<ret[j-1])
{
bigInteger tmp = ret[j];
ret[j] = ret[j-1];
ret[j-1] = tmp;
}
}
}
//cout << endl;
for(int i=0; i<n; i++)
{
ret[i].output();
}
}
int main()
{
int N;
bigInteger ret[101];
char str[MAX];
while(cin >> N)
{
for(int i=0; i<N; i++)
{
scanf("%s", str);
ret[i].init();
ret[i].set(str);
//ret[i].output();
}
bigIntegerSort(ret, N);
}
return 0;
}