一本通 高精度专栏

A 求N!的值

【问题描述】

用高精度方法,求N!的精确值(N以一般整数输入)。

【输入形式】

【输出形式】

样例输入】

10

【样例输出】

3628800

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 

int n;
int a[2005];



int main(){  
   std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
    a[0] = 1;
    for(int i = 1 ; i <= n ; i ++ ){
    	int b = 0 ;
    	int s;
    	for(int j = 0 ; j < 2000 ; j ++ ){
    		 s = a[j] * i + b;
    		 a[j] = s % 10;
    		 b = s / 10;
		} 
	}
    
    int i;
    for(i = 2004 ; i >= 0 ; i-- )
     if(a[i] != 0) break;
    for(int j = i ; j >= 0 ; j--)
     cout<<a[j];
	return 0;
}

B 求A/B高精度值

【问题描述】

计算A/B的精确值,设A,B是以一般整数输入,计算结果精确到小数后20位(若不足20位,末尾不用补0)。

【输入形式】

【输出形式】

【样例输入1】

4 3

【样例输出1】

4/3=1.33333333333333333333

【样例输入2】

6 5

【样例输出2】

6/5=1.2


#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 

int a,b;
int c[25];

int main(){  
   std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> a >> b;
    cout<< a<<"/"<<b<<"=" <<a/b<<".";
    for(int i = 1 ; i <= 20 ; i++ ){
    	 a = a % b ;
    	 a = a * 10;
    	 c[i] = a / b ;
	}
	int i = 20;
	while(c[i] == 0 && i >=0 ) i--;
	for(int j = 1 ; j <= i ; j++)
	 cout<<c[j];
	return 0;
}

C 求n累加和

【问题描述】

用高精度方法,求s=1+2+3+……+n的精确值(n以一般整数输入)。

【输入形式】

【输出形式】

【样例输入】

10
【样例输出】

55


#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 

ll a[2005],b[2005],c[2005],d[2005];
ll n;

void change(int num,ll a[]){
	int cnt = 0;
	while(num/10){
		 a[++cnt] = num%10;
		 num/=10;
	}
	while(num/10 == 0 && num >0){
		 a[++cnt] = num;
		 num/=10;
	}
	a[0] = cnt;
}

void add(ll a[],ll c[]){
	 int  i , x = 0;
	 for( i = 1 ; i <= a[0] || i <= c[0] ; i++ ){
	 	 c[i] = c[i] + a[i] + x;
	 	 x = c[i] / 10;
	 	 c[i] = c[i] % 10;
	 }
	 c[i] = x;
	 if(c[i] == 0 ) c[0] = i - 1;
	  else  c[0] = i;
}

void cf(ll a[],ll b[],ll c[]){
	int i , j ;
	for(int i = 1 ; i <= b[0] ; i ++){
		 int x;
		 for(int j = 1 , x = 0 ; j <= a[0] ; j++ ){
		 	 c[i+j-1] += a[j] * b[i] + x;
		 	 x = c[i+j-1]/10;
		 	 c[i+j-1]%=10;
		 }
		 c[i+a[0]] = x;
	} 
	int l = a[0] + b[0];
	while(c[l] == 0 && l > 1) l--;
	c[0] = l;
}
int main(){  
   std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n ;
    change(n + 1 , a);
    change(n / 2 , b);
    cf(a , b , c);
    if(n&1){
    	change(n/2+1,d);
    	 add(d,c);
	}
    for(int j = c[0] ; j >= 1 ; j-- )
     cout<<c[j];
	return 0;
}

D 阶乘和

【问题描述】

已知正整数N(N<=100),设S=1!+2!+3!+…N!。其中"!"表示阶乘,即N!=123*……(N-1)N,如:3!=123=6。请编程实现:输入正整数N,输出计算结果S的值。

【输入形式】

【输出形式】

【样例输入】

4
【样例输出】

33


#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 

int n;
int t[MAX],res[MAX],len = 1,reslen;
void jiechen(int v){
	for(int i = 1 ; i <= len ; i ++ )
		t[i] = t[i] * v;
		
	 int i=1;
	 while(t[i]>9||i<len)
	 {
	 	t[i+1]+=t[i]/10;
	 	t[i]%=10;
	 	i++;
	 }
	 len=i;
	
}
void add(){
	for(int i=1;i<=len;i++)
	{
		res[i]+=t[i];
		if(res[i]>9)
		{
			res[i+1]+=res[i]/10;
			res[i]%=10;
			reslen=max(reslen,i+1);
		}
		reslen=max(reslen,i);
	}
}
int main(){  
   std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
    t[1] = 1;
    for(int i = 1 ; i <= n ; i++ ) jiechen(i),add();
    for(int i = reslen ; i >=1;i--)
    cout<<res[i];
	return 0;
}

E 高精度求积

【问题描述】

输入两个高精度正整数M和N(M和N均小于100位)。

求这两个高精度数的积。

【输入形式】

输入两个高精度正整数M和N。

【输出形式】

求这两个高精度数的积。

【样例输入】

36

3

【样例输出】

108


#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 

string s1,s2;
int a[MAX],b[MAX],c[MAX];
int len1,len2,len3;

int main(){  
   std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> s1 >> s2;
    if(s1[0] == '0' || s2[0] == '0'){
    	 cout<<0;
    	 return 0;
	}
	len1 = s1.length() ;
	len2 = s2.length() ;
	
	for(int i = 0 ; i < len1 ; i ++ )
	 a[len1 - i ] = s1[i] - '0';
	for(int i = 0 ; i < len2 ; i ++ )
	 b[len2 - i ] = s2[i] - '0';
	
	for(int i = 1 ; i <= len2 ; i++ ){
		 int k = 0;
		 for(int j = 1 ; j <= len1 ; j ++){
		 	c[i + j - 1] = a[j] * b[i] + c[i+j-1];
            k=c[i + j - 1]/10;
            c[i + j - 1]%=10;
            c[i + j] += k;
		 } 
	}
	
	len3=len1+len2;
    for(int j=len3;j>=1;j--)
    if(c[j]!=0) break;
     else len3--;
    for(int j=len3;j>=1;j--)
        cout<<c[j];
	return 0;
}

F 天使的起誓

【问题描述】

TENSHI非常幸运地被选为掌管智慧之匙的天使。在正式任职之前,她必须和其他新当选的天使一样,要宣誓。宣誓仪式是每位天使各自表述自己的使命,她们的发言稿被放在n 个呈圆形排列的宝盒中。这些宝盒按顺时针方向被编上号码1、2、3……、n-1、n。一开始天使们站在编号为N 的宝盒旁。她们各自手
上都有一个数字,代表她们自己的发言稿所在的盒子是从1号盒子开始按顺时针方向的第几个。例如:有7个盒子,那么如果TENSHI 手上的数字为9,那么她的发言稿所在盒子就是第2 个。现在天使们开始按照自己手上的数字来找发言稿,先找到的就可以先发言。TENSHI 一下子就找到了,于是她最先上台宣誓:“我将带领大家开启NOI 之门……”TENSHI 宣誓结束以后,陆续有天使上台宣誓。可是有一位天使找了好久都找不到她的发言稿,原来她手上的数字M 非常大,她转了好久都找不到她想找的宝盒。请帮助这位天使找到她想找的宝盒的编号。

【输入形式】

从文件 的第一、二行分别读入正整数n 和m,其中n、m 满足 2 ≤ n≤ 108,2 ≤ m≤ 101000

【输出形式】

把所求宝盒的编号输出,文件只有一行(包括换行符)。

【样例输入1】

7
9

【样例输出1】

2

【样例输入2】

11

108

【样例输出2】

9


#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 

int n;
ll ans ;
char s[MAX];

int main(){  
   std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    string s;
    cin >> n >> s;
  
    for(int i=0;s[i] ;i++) 
	 ans=(ans*10+s[i]-'0')%n;
	 
    if(ans == 0 ) cout<<n;
     else cout<<ans;
	return 0;
}

G Hanoi 双塔问题

【问题描述】

给定A、B、C 三根足够长的细柱,在A 柱上放有2n 个中间有孔的圆盘,共有n 个不同的尺寸,每个尺寸都有两个相同的圆盘,注意这两个圆盘是不加区分的(下图为n=3 的情形)。现要将这些圆盘移到C 柱上,在移动过程中可放在B 柱上暂存。要求:
(1)每次只能移动一个圆盘;
(2)A、B、C 三根细柱上的圆盘都要保持上小下大的顺序;任务:设An为2n个圆盘完成上述任务所需的最少移动次数,对于输入的n,输出An。

【输入形式】

输入文件为一个正整数n,表示在A 柱上放有2n 个圆盘。

【输出形式】

输出仅一行,包含一个正整数, 为完成上述任务所需的最少移动次数An。

【样例输入1】
1
【样例输出1】
2
【样例输入2】
2
【样例输出2】
6


#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 
int n ,a[205],b[205];
void gjc(){
	int t = 0,k;
	for(int j = 200 ; j > 0 ;j--){
		 k = b[j] * 2 + t;
		 b[j] = k % 10;
		 t = k / 10;
	}
}
void gjj(){
	int t = 0 ,k;
	for(int j = 200 ; j > 0 ; j-- ){
		 k = a[j] + b[j] + t;
		 a[j] = k % 10;
		 t = k / 10;
	}
}
int main(){  
   std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
    b[200] = 1;
    for(int i = 1;i <= n ; i++) gjc(),gjj();
	
	int k = 1;
	while(a[k] == 0 && k < 200) k ++ ;
	for(int i = k ; i <= 200 ; i++ )
	 cout<<a[i]; 
	return 0;
}

H 高精除

【问题描述】

高精除以高精,求它们的商和余数。

【输入形式】

输入两个低于300位的正整数。

【输出形式】

输出商和余数。

【样例输入】

1231312318457577687897987642324567864324567876543245671425346756786867867867
1231312318767141738178325678412414124141425346756786867867867

【样例输出】

999999999748590
179780909068307566598992807564736854549985603543237528310337

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;

int a[101], b[101], c[101], d;

void init(int a[]) {
	string s;
	cin >> s;						// 读入字符串s
	a[0] = s.length();				// 用a[0]计算字符串s的位数
	for (int i=1; i<=a[0]; i++) {
		a[i] = s[a[0]-i] - 48;		// 将数串s转换为数组a,并倒序存储 
	} 	
}

void print(int a[]) {				// 打印输出 
	if (a[0] == 0) {
		cout << 0 << endl;
		return;
	}
	for (int i=a[0]; i>=1; i--) {
		cout << a[i];
	}
	cout << endl;
	return;
} 

int compare(int a[], int b[]) {		// 比较a和b的大小关系,若a>b则为1,a<b则为-1,a=b则为0
	if (a[0] > b[0]) {
		return 1;
	} 
	if (a[0] < b[0]) {
		return -1;
	}
	for (int i=a[0]; i>=1; i--) {	// 从高位到低位比较 
		if (a[i] > b[i]) {
			return 1;
		} 
		if (a[i] < b[i]) {
			return -1;
		}
	} 
	return 0;						// 各位都相等则两数相等 
}

void numcpy(int p[], int q[], int det) {	// 复制p数组到q数组从det开始的地方 
	for (int i=1; i<=p[0]; i++) {
		q[i+det-1] = p[i];
	}
	q[0] = p[0] + det - 1;
}

void jian(int a[], int b[]) {			// 计算 a=a-b 
	int flag = compare(a, b);			// 调用比较函数判断大小 
	if (flag == 0)  {					// 相等 
		a[0] = 0;
		return;
	}
	if (flag == 1) {					// 大于 
		for (int i=1; i<=a[0]; i++) {
			if (a[i] < b[i]) {			 
				a[i+1]--;				// 若不够减,则向上借一位 
				a[i] += 10;
			}
			a[i] -= b[i];
		}
		while (a[0]>0 && a[a[0]]==0) {
			a[0]--;						// 修正a的位数 
		} 
		return; 
	}				 
}

void chugao(int a[], int b[], int c[]) {
	int tmp[101];
	
	c[0] = a[0] - b[0] + 1;
	for (int i=c[0]; i>0; i--) {
	
		memset(tmp, 0, sizeof(tmp));		// 数组清零
		numcpy(b, tmp, i);

		while (compare(a, tmp) >= 0) {
			c[i]++;
			jian(a, tmp);
								// 用减法来模拟 
		} 
	}
	while (c[0]>0 && c[c[0]]==0) {
		c[0]--;
	}
	return;
}

int main() {
	memset(a, 0, sizeof(a));
	memset(b, 0, sizeof(b));
	memset(c, 0, sizeof(c));
	
	init(a);
	init(b);
	 
	chugao(a,b,c);
	
	print(c);
	print(a);
	
	return 0;
}

I 回文数

【问题描述】

若一个数(首位不为零)从左向右读与从右向左读都是一样,我们就将其称之为回文数。例如:给定一个 10进制数 56,将 56加 65(即把56从右向左读),得到 121是一个回文数。又如,对于10进制数87,
STEP1: 87+78= 165 STEP2: 165+561= 726
STEP3: 726+627=1353 STEP4:1353+3531=4884
在这里的一步是指进行了一次N进制的加法,上例最少用了4步得到回文数4884。
写一个程序,给定一个N(2<N<=10或N=16)进制数 M.求最少经过几步可以得到回文数。如果在30步以内(包含30步)不可能得到回文数,则输出“Impossible!” 。

【输入形式】

给定一个N(2<N<=10或N=16)进制数M。

【输出形式】

最少几步。如果在30步以内(包含30步)不可能得到回文数,则输出“Impossible!”。

【样例输入】

9 87

【样例输出】

STEP=6


#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 

char c[305],d[305];
int n,step,len;

void add(){
	for(int i = 0 ; i < len ; i ++)
	 d[len - i - 1] = c[i];
	 
	 len += 2 ;
	for(int i = 0 ; i < len ; i ++ ){
		 c[i] += d[i];
		 if(c[i] >= n) c[i+1] ++, c[i] -= n;
	}
	while(!c[len - 1]) len -- ;
}

int judge(){
	for(int i = 0 ; i < len ; i ++){
		 if(c[i] != c[len - 1 - i]) return 0;
	}
	return 1;
	
}
int main(){  
   std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> c;
    len = strlen(c);
    for(int i = 0 ; c[i] ; i ++ ){

    	 if(c[i] >='0' && c[i] <='9') c[i] -= '0';
    	  else  c[i] = c[i] - 'A' + 10;
    	  
	}
	while(!judge()){
		step++;
		if(step>30) break;
		add();
	}
	if(step <= 30) cout<<"STEP="<<step;
	 else cout<<"Impossible!";
	 
	return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值