NOIP大纲整理:(三)读写外挂与高精度模板

97 篇文章 1 订阅
26 篇文章 6 订阅

读入输出挂(提高组才需要,普及以下,只要了解一下机制就可以了

读入输出挂就是逐个字符地读入数据,从而让读入更加快速。输出挂的原理也是一样的,都是通过将输出数字变成输出字符以加快速度。当然输入输出外挂一般用在大量输入输出的情况下,这样性价比才高一些,否则得不偿失。

暂时代码是转载的,以后有机会会更新,看不懂请跳过

void Rd(int &res){
    res=0;char p;
    while(p=getchar(),p<'0');
    do{
       res=(res<<1)+(res<<3)+(p^48);
    }while(p=getchar(),p>='0');
}
void Rd(int &res){
    res=0;char p;int k=1;
    while(p=getchar(),!(p>='0'&&p<='9')&&p!='-');
    if(p=='-')k=-1,p=getchar();
    do{
       res=(res<<1)+(res<<3)+(p^48);
    }while(p=getchar(),(p>='0'&&p<='9'));
    res*=k;
}
void Pt(int x){
    if(x==0)return;
    Pt(x/10);
    putchar(x%10^48);
}
void Ps(int x){
    if(x<0)putchar('-'),x=-x;
    if(x==0)putchar('0');
    else Pt(x);
}

 


 高精度算法

1、高精度加法(简单版,以noi1.6:10大整数加法题为例)

//noi1.6:10大整数加法
//题解:高精度入门题:结构体+字符转换+进位 
#include<cstdio>
#include<cstring>
struct nod{int n,a[210];nod(){memset(a,0,sizeof(a));}}a,b;
char s[210];
int main()
{
	int ns;//读入a============ 
	scanf("%s",s+1);//下标从1开始 
	ns=strlen(s+1);	a.n=ns;
	for(int i=1;i<=ns;i++)//字符逆序转换为数字 
	{//为了数位 对齐,翻转数字 
		a.a[ns-i+1]=s[i]-'0';
	}//========================
	
	//读入b==================== 
	scanf("%s",s+1);//下标从1开始 
	ns=strlen(s+1);	b.n=ns;
	for(int i=1;i<=ns;i++)//字符逆序转换为数字 
	{//为了数位 对齐,翻转数字 
		b.a[ns-i+1]=s[i]-'0';
	}//=========================
	//模拟加法运算 
	a.n=a.n>b.n?a.n:b.n;//确定数位 
	for(int i=1;i<=a.n;i++)//暴力加 
	{
		a.a[i]+=b.a[i];
	}
	for(int i=1;i<=a.n;i++)//处理进位 
	{
		if(a.a[i]>9)
		{
			a.a[i+1]+=a.a[i]/10;//向右进位 
			a.a[i]%=10;//保留个位数
			if(i==a.n) a.n++;//最高位溢出 
		}
	}
	//消除前导0
	while(a.a[a.n]==0&&a.n>1) a.n--;//最高位必须非0
	//反向输出
	for(int i=a.n;i>=1;i--)
	{
		printf("%d ",a.a[i]);
	} 
	return 0;
}


2、高精度减法(简单版,以noi1.6:11大整数减法题为例)

//noi1.6:11大整数减法
//题解:高精度入门题:结构体+字符转换+借位 
#include<cstdio>
#include<cstring>
struct nod{int n,a[210];nod(){memset(a,0,sizeof(a));}}a,b;
char s[210];
int main()
{
	int ns;//读入a============ 
	scanf("%s",s+1);//下标从1开始 
	ns=strlen(s+1);	a.n=ns;
	for(int i=1;i<=ns;i++)//字符逆序转换为数字 
	{//为了数位 对齐,翻转数字 
		a.a[ns-i+1]=s[i]-'0';
	}//========================
	//读入b==================== 
	scanf("%s",s+1);//下标从1开始 
	ns=strlen(s+1);	b.n=ns;
	for(int i=1;i<=ns;i++)//字符逆序转换为数字 
	{//为了数位 对齐,翻转数字 
		b.a[ns-i+1]=s[i]-'0';
	}//=========================
	//模拟减法运算  
	for(int i=1;i<=a.n;i++) a.a[i]-=b.a[i];//暴力减 
	for(int i=1;i<=a.n;i++)//处理借位 
	{
		if(a.a[i]<0)
		{
			a.a[i+1]-=1;//向右借 1 
			a.a[i]+=10;//补充数值 
		}
	}
	//消除前导0//本题保证a>b,如果不知道大小关系呢? 
	while(a.a[a.n]==0&&a.n>1) a.n--;//最高位必须非0
	//反向输出
	for(int i=a.n;i>=1;i--) printf("%d",a.a[i]);
	return 0;
}

3、高精度乘法(有两种:高精度*低精度,高精度*高精度)

(以下代码只展示高精度*低精度,以noi1.6:12:计算2的N次方 题为例)

//noi1.6:12计算2的N次方 
//题解:高精度*低精度 +非结构体 +函数 
#include<cstdio>
int a[1010],na;//估算数组,2的100次不知道是多少位?
//10的100次是1000位,可以了吗?
void cf(int x)
{
	for(int i=1;i<=na;i++)//每位都乘 
	{
		a[i]*=x;
	}
	for(int i=1;i<=na;i++)//处理进位 
	{
		if(a[i]>9)
		{
			a[i+1]+=a[i]/10;
			a[i]%=10;
			if(i==na) na++;//最高位溢出 
		}
	}
}
int main()
{
	int n;
	scanf("%d",&n);
	a[1]=1;na=1;
	for(int i=1;i<=n;i++)
	{
		cf(2);
	}
	for(int i=na;i>=1;i--) printf("%d",a[i]);//反向输出 
	
	//现在你可以知道2的100次方是多少位了吗? 
	
	return 0;
}


4、高精度除法(有两种:高精度/低精度,高精度/高精度)

(以下代码只展示高精度/低精度,以noi1.6:13:大整数的因子 题为例)

//noi1.6:13大整数的因子 
//题解:高精度除以低精度:模拟思想 
#include<cstdio>
#include<cstring>
char s[210];
int a[210],na,ls=0; 
void chu(int x)
{
	int k=0;//余数 
	for(int i=na;i>=1;i--)//模拟竖式除法 
	{
		k=k*10+a[i];
		k=k%x;
	}
	if(k==0) 
	{	ls=1; //打标签 
		printf("%d ",x);
	} 
}
int main()
{
	int ns;
	scanf("%s",s+1);//下标从1开始 
	ns=strlen(s+1);	na=ns;
	for(int i=1;i<=ns;i++)//字符逆序转换为数字 
	{
		a[ns-i+1]=s[i]-'0';
	}
	for(int i=2;i<=9;i++)
	{
		chu(i);//函数处理 
	}
	if(ls==0) printf("none"); 
	return 0;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值