7-6 考试座位号
输入样例:
4
3310120150912233 2 4
3310120150912119 4 1
3310120150912126 1 3
3310120150912002 3 2
2
3 4
输出样例:
3310120150912002 2
3310120150912119 1
解决方案:
由题目可以发现,只需通过建立映射关系知晓测试机号的对应ID和考试位置即可,于是,我们采用map给予解决
代码
#include<iostream>
#include<map>
#include<string>
using namespace std;
map<int,int>ExamPlace;
map<int,string>ID;
int main()
{
int n,m;cin>>n;string info;int Test,Exam;
for(int i=0;i<n;i++){
cin>>info>>Test>>Exam;
ExamPlace[Test]=Exam;
ID[Test]=info;
}
cin>>m;
int t;
for(int i=0;i<m;i++){
cin>>t;
cout<<ID[t]<<" "<<ExamPlace[t]<<endl;
}
return 0;
}
7-7 重排链表
代码如下
#include<iostream>
#include<map>
#include<vector>
using namespace std;
typedef struct{
int Address;
int Data;
int Next;
}Seq;
Seq seq[1000000];
map<int,int>dataofadd;//
map<int,int>nextofadd;
vector<Seq> origin;
vector<Seq> result;
int main()
{
int n;int add;int da;
int originadd;
cin>>originadd>>n;
for(int i=0;i<n;i++){
int a,b,c;//对于map的初定义问题
//此处产生1个链式结构初始内容
cin>>a>>b>>c;
add=a;
dataofadd[add]=b;
nextofadd[add]=c;
}
int sq;
for(add=originadd,sq=1;add!=-1;sq++,add=nextofadd[add])
{//形成vector,以便后续操作
seq[sq].Address=add;
seq[sq].Data=dataofadd[add];
seq[sq].Next=nextofadd[add];
origin.push_back(seq[sq]);
}
int first=0;int last=n-1;
while (first <= last) {//对于第一个地址,和最后一个内容
if (first <= last)result.push_back(origin[last--]);
if (first <= last)result.push_back(origin[first++]);
}
for (int i = 0; i < result.size()-1; i++)
printf("%05d %d %05d\n", result[i].Address, result[i].Data, result[i + 1].Address);
printf("%05d %d %d\n", result[result.size() - 1].Address, result[result.size() - 1].Data,-1);
return 0;
}
简化版本
一.经过对第一种版本的修整,将vector换成了
deque,使得要解决的问题更加明了,代码更加易懂
二.将存放的数据改为data,减少了空间消耗
#include<iostream>
#include<map>
#include<vector>
#include<stdio.h>
#include<deque>
using namespace std;
map<int,int> add;
map<int,int> id;
map<int,int> nextadd;
deque<int> seq;
int main()
{
int n;int tadd,tnextadd,x;
int firstadd;int num;
cin>>firstadd>>n;
for(int i=0;i<n;i++){
cin>>tadd>>x>>tnextadd;
add[x]=tadd;
nextadd[x]=tnextadd;
id[tadd]=x;
if(tadd==firstadd) num=x;
}
for(x=num;nextadd[x]!=-1;x=id[nextadd[x]])
{
seq.push_back(x);
}
seq.push_back(x);
int t;
while(!seq.empty())
{
t=seq.back();
if(seq.size()!=1) printf("%05d %d %05d\n",add[t],t,add[seq.front()]);
else {printf("%05d %d -1\n",add[t],t);break;}
seq.pop_back();
t=seq.front();
if(seq.size()!=1) printf("%05d %d %05d\n",add[t],t,add[seq.back()]);
else {printf("%05d %d -1\n",add[t],t);break;}
seq.pop_front();
}
return 0;
}
总结:题目让我们进行重排,由其头尾交替输出我们可以想到使用
double-end-queue
对于这种数据域较少的数据结构,我们可以考虑使用map来简化,用于确定对应数据关系
7-13斐波那契数列
已知斐波那契数列 F
求解该数列的第n项,结果对998244353取模。
提示:矩阵快速幂,unsigned long long的最大值:1844674407370955161(1.8e18)
解决方案:
由于该问题的数值巨大,我们不得不拿出大杀器,矩阵快速幂。
矩阵快速幂简化了计算过程,利用了已有的计算结果推出下一个计算结果,最大化利用了资源
具体原理
下面的pow函数就是利用了以上原理,通过前面算后面,省略为0的项
代码
#include<iostream>
#include<memory.h>
using namespace std;
typedef long long ll;
const int mod=998244353;
const int N=2;
ll tmp[N][N],res[N][N];
void multi(ll a[][N],ll b[][N],int n)
{
memset(tmp,0,sizeof(tmp));
for(ll i=0;i<n;i++) {
for(ll j=0;j<n;j++){
for(ll k=0;k<n;k++){
tmp[i][j]+=(a[i][k]*b[k][j])%mod;
}
tmp[i][j]=tmp[i][j]%mod;
}
}
for(ll i=0;i<n;i++)
for(ll j=0;j<n;j++)
a[i][j]=tmp[i][j];
}
void Pow(ll a[][N],ll m,int n)
{
memset(res,0,sizeof(res));//m是几次幂,n是矩阵大小
for(ll i=0;i<n;i++) res[i][i]=1;
while(m){
if(m&1)
multi(res,a,n);//res=res*a;
multi(a,a,n);//a=a*a
m>>=1;
}
}
int main()
{
ll m;
int n;
ll a[N][N];
scanf("%lld",&m);
n=2;
a[0][0]=1,a[0][1]=1,a[1][0]=1,a[1][1]=0;
Pow(a,m,n);
printf("%lld\n",res[1][0]);
return 0;
}