2021-02-21

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值