模拟和高精度洛谷总结

 

目录

A.玩具谜题

分析:

注意:

代码:

B. A+B  Problem高精

分析:

注意:

代码:

C.A*B  Problem

分析:

注意:

代码:

D.阶乘之和

分析:

注意:

代码:

E.魔法少女小Scarlet

分析:

注意:

代码:

总结:

A.玩具谜题

  

分析:

①这道题就是一道模拟题,自己根据题意进行分析,对可能出现的情况进行分类→②可以大致总结出来这里玩具们围起了一个圆圈,然后会出现顺时针和逆时针两种计数情况→③分好情况后再进行计数的公式的推导(找规律)

注意:

①这里需要用到结构体,因为要对一个玩具的序号以及朝向进行记录

②在做数组的题的时候,最好在一开始根据数据的大小把数组开好,不然后面可能会卡数据!!!

③还有就是玩具的编号,我最开始是从1开始的,就一直不能AC,后来发现是因为推导公式我没有考虑到余数会是0的情况,所以这里的玩具计数要从0开始,但是如果想要从1开始还是可以,就需要重新推导公式

代码:

#include<bits/stdc++.h>
using namespace std;

struct Men{
	int face;
	char name[15];
};
struct Mm{
	int drt;
	int num;
};
Men men[1000005];//最开始的只有60分就是因为数组没有开大 
Mm mm[10000005];
int main()
{
	int n,m;
	scanf("%d %d",&n,&m);
	//因为在下面的公式会出现刚好没有余数的情况,所以只能从0开始存储!!!! 
	for(int i=0;i<n;i++)scanf("%d %s",&men[i].face,men[i].name);//为什么修改了k和i的值,从1开始就会出现问题? 
	int k=0;//都是从第一个小人开始的 
	for(int i=1;i<=m;i++){
		scanf("%d %d",&mm[i].drt,&mm[i].num);
		if(men[k].face!=mm[i].drt){//逆时针加减
			k=(k+mm[i].num)%n;
		}
		else if(men[k].face==mm[i].drt){ //顺时针加减 
			k=(k+n-mm[i].num)%n;
		}
	}
	printf("%s\n",men[k].name);
	return 0;
 } 

B. A+B  Problem高精

 

分析:

就是高精度加法,模板题

注意:

vector的使用,这里是一个公式题,记住模板就可以了

②还有就是字符于数字的转化问题,例如a[i]-'0'

auto是对函数返回的值进行定义

④这里的加法是从个位数开始的,所以存储数据是倒序存储的,一定注意是i--,不是i++(一直犯的错误TAT)

代码:

#include<bits/stdc++.h>
using namespace std;
vector<int> add(vector<int> &A,vector<int> &B)
{
	if(A.size()<B.size())return add(B,A);
	vector<int> C;
	int t=0;
	for(int i=0;i<A.size();i++){
		t+=A[i];
		if(i<B.size())t+=B[i];
		C.push_back(t%10);
		t/=10;
	}
	if(t>0)C.push_back(t);
	return C;
}

int main()
{
	string a,b;
	cin>>a>>b;
	vector<int> A,B;
	for(int i=a.size()-1;i>=0;i--)A.push_back(a[i]-'0');
	for(int i=b.size()-1;i>=0;i--)B.push_back(b[i]-'0');
	auto C=add(A,B);
	for(int i=C.size()-1;i>=0;i--)printf("%d",C[i]);
	return 0;
}

C.A*B  Problem

 

分析:

高精度乘法题,但是这个和高精度乘法模板不太一样,高精度模板是高精度*低精度

注意:

①这里是高精度*高精度

②高精度*高精度需要提前开好动态数组的大小!!!同时开的数组的赋值都为0,例如vector<int>C(A.size()+B.size()+10,0)

③还有就是数组C的存储,C[i+j] += A[i]*B[i]

对数组C在进行进位以及分成一个一个数的处理,C[i+1] += C[i]/10; C[i]%=10

⑤因为提前开好了数组,所以还要进行前导0的处理

代码:

#include <bits/stdc++.h>
using namespace std;

vector<int>mul (vector<int>&A,vector<int>&B)
{
	vector<int>C(A.size()+B.size()+10,0);
	for(int i=0;i<A.size();i++){
		for(int j=0;j<B.size();j++){
			C[i+j]+=A[i]*B[j];
		}
	}
	for(int i=0;i+1<C.size();i++){
		C[i+1]+=C[i]/10;
		C[i]%=10;
	}
	while(C.size()>1&&C.back()==0)C.pop_back();
	return C;
}
int main()
{
	string a,b;
	vector<int> A,B,C;
	cin>>a>>b;
	
	for(int i=a.size()-1;i>=0;i--)A.push_back(a[i]-'0');
	for(int i=b.size()-1;i>=0;i--)B.push_back(b[i]-'0');
	C=mul(A,B);
	
	for(int i=C.size()-1;i>=0;i--)printf("%d",C[i]);
	return 0;
 } 

D.阶乘之和

 

分析:

因为这里的n取到了50,所以需要用到高精度加法和乘法的结合!!!

注意:

①这里用到了数组,所以需要提前开启数组,这里需要把数据开到符合数据范围的数组,所以我们需要进行估值

②两个数相加结果的位数不会超过两者中较大数+1,我们可以知道50!大概是65位数,所以我们数组最大应该是66

③为了防止出现数据越界,这里是把一个数的阶层算出,然后进行分成一个数一个数的处理,最后再进行一个数一个数的加减

④提前开数组都要注意前导0的处理,这里的前导0 的处理于前面的题的处理存在一些区别,for(int k=N-1;a[k]==0&&k>0,k--)记录非0的位置

代码:

#include<bits/stdc++.h>
using namespace std;

//这里还是之前一直说的注意数据范围一样!!! 
const int N=66;//这道题的一个难点之一就是这里对50!数值的估算,这里50!为65,所以我们最大值取66,因为两个数字相加,结果的位数最大只能是相加的两个数的较大者+1 
int a[N],b[N]; 
int main()
{
	int n;
	scanf("%d",&n);
	a[0]=b[0]=1;//直接把a[0]b[0]赋值为1,所有的都从2开始 
	for(int i=2;i<=n;i++){//因为是n的阶层,所以循环n次 
		for(int j=0;j<N;j++){
			b[j]*=i;
		}
		for (int j=0;j<N;j++){//模拟进位
                b[j + 1] += b[j]/10;
                b[j]%=10;
			}
		for(int j=0;j<N;j++){//提前开好了的a数组,所以直接用处理好的b进行加减 
			a[j]+=b[j];
			a[j+1]+=a[j]/10;
			a[j]%=10; 
		}
	} 
	int k;//记录前导0去掉的位置
	for(k=N-1;k>=0&&a[k]==0;k--);
	for(int i=k;i>=0;i--)printf("%d",a[i]);//从最大位数开始输出 
	return 0;
}

E.魔法少女小Scarlet

 

 

分析:

①这是一道模拟题,先对题目进行分析得出这是→②这里已经明确了有两种情况,我们模拟应该要清楚的是方阵变换行列变换的规律!!!→③找出规律,得出相应的变换公式(这个也是这个题的难点,就算你清楚了,最后怎么用代码表达也是存在问题的,我就是在这里卡了很久QAQ)如果是顺时针:i 行变为i列;逆时针:i 行变成倒数i列

注意:

①还是是公式问题,找规律是个问题TAT

②还需要开一个暂时存储矩阵变化的数组

代码:

#include<bits/stdc++.h>
using namespace std;
int g[510][510],tot,f[510][510];//f数组充当临时数组 
int main(){
	int n,m;
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			g[i][j]=++tot;
	for(int i=1;i<=m;i++) {
		int a,b,r,opt;
		scanf("%d %d %d %d",&a,&b,&r,&opt);//下面的分析都是针对那一块矩阵而言的 
		if(opt==0) {//第i行第j个 变成倒数第i列第j个 顺时针 
			for(int i=a-r;i<=a+r;i++)
				for(int j=b-r;j<=b+r;j++)
					f[a-b+j][a+b-i] = g[i][j];
			for(int i=a-r;i<=a+r;i++)
				for(int j=b-r;j<=b+r;j++)
					g[i][j] = f[i][j];
		}
		else { //第i行第j个 变成第i列倒数第j个 逆时针 
			 for(int i=a-r;i<=a+r;i++)
				for(int j=b-r;j<=b+r;j++)
					f[a+b-j][b-a+i] = g[i][j];
			 for(int i=a-r;i<=a+r;i++)
				for(int j=b-r;j<=b+r;j++)
					g[i][j] = f[i][j];
		}
	}
	for(int i=1;i<=n;i++) {//输出结果咯 
		for(int j=1;j<=n;j++)
			printf("%d ",g[i][j]);
		printf("\n");
	}
	return 0;
} 

总结:

模拟:(玩具谜题和魔法少女小Scarlet)

找规律!!!→ 得到公式

高精度:(A+B Problem,A*B Problem,阶乘之和)

前导0的处理

字符和整数的转化

vector 的应用,如何提前开好数组,如何存储的问题

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值