目录
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 的应用,如何提前开好数组,如何存储的问题