2022.7.26刷题合集

目录

1、矩阵快速幂

2、KMP字符串匹配

3、口袋的天空

4、Barn Echoes G

5、租用游艇

6、shortest path of the king


1、矩阵快速幂

#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;
const int maxn=105,p=1e9+7;
int n;
struct Matrix{
    LL m[maxn][maxn];
    Matrix(){
        memset(m,0,sizeof m);
    }
    void build(){
        for(int i=1;i<=n;i++) m[i][i]=1;
    }
};

Matrix operator *(const Matrix &A,const Matrix &B){
    Matrix res;
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                res.m[i][j]=(res.m[i][j]+A.m[i][k]*B.m[k][j]%p)%p;
    return res;
}

LL k;

int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n>>k;
    Matrix ans,start;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            cin>>start.m[i][j];
    ans.build();
    while(k){
        if(k&1) ans=ans*start;
        start=start*start;
        k>>=1;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cout<<ans.m[i][j]<<" ";
        }
        cout<<endl;
    }
    return 0;
}

2、KMP字符串匹配

经过了移位处理的数据更方便运算,用短串的j+1位和长串的第i位匹配,如果相同j++,不相同j=ne[j],如果两个相同了说明匹配成功了。

求next数组的过程和匹配过程差不多,就是将两个相同的串匹配就是了

#include<iostream>
#include<cstring>
using namespace std;
const int N=1e6+10;
char S[N],P[N];
int ne[N];
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>(S+1)>>(P+1);
    int la=strlen(S+1);
    int lb=strlen(P+1);
    for(int i=2,j=0;i<=lb;i++){
        while(j&&(P[j+1]!=P[i])) j=ne[j];
        if(P[j+1]==P[i]) j++;
        ne[i]=j;
    }
    for(int i=1,j=0;i<=la;i++){
        while(j&&(P[j+1]!=S[i])) j=ne[j];
        if(P[j+1]==S[i]) j++;
        if(j==lb){
            cout<<i-lb+1<<endl;
        }
    }
    for(int i=1;i<=lb;i++) cout<<ne[i]<<" ";
    return 0;
}

3、口袋的天空

Kruskal裸题

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e3+10,M=1e4+10;
struct Edge{
    int x,y,w;
    bool operator < (const Edge &B) const {
        return w<B.w;
    }
}edges[M];
int n,m,k;
int p[N];
int find(int x){
    if(p[x]!=x) p[x]=find(p[x]);
    return p[x];
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n>>m>>k;
    for(int i=0;i<m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        edges[i]={a,b,c};
    }
    sort(edges,edges+m);
    for(int i=0;i<n;i++) p[i]=i;
    int len=0,cost=0;
    for(int i=0;i<m;i++){
        int a=edges[i].x,b=edges[i].y,w=edges[i].w;
        a=find(a),b=find(b);
        if(a!=b){
            p[a]=b;
            cost+=w;
            len++;
        }
        if(len>=n-k) break;
    }
    if(len<n-k) cout<<"No Answer"<<endl;
    else cout<<cost<<endl;
    return 0;
}

4、Barn Echoes G

 中文题面

奶牛们非常享受在牛栏中哞叫,因为她们可以听到她们哞声的回音。虽然有时候并不能完全听到完整的回音。Bessie曾经是一个出色的秘书,所以她精确地纪录了所有的哞叫声及其回声。她很好奇到底两个声音的重复部份有多长。

输入两个字符串(长度为1到80个字母),表示两个哞叫声。你要确定最长的重复部份的长度。两个字符串的重复部份指的是同时是一个字符串的前缀和另一个字符串的后缀的字符串。

我们通过一个例子来理解题目。考虑下面的两个哞声:

moyooyoxyzooo

yzoooqyasdfljkamo

第一个串的最后的部份"yzooo"跟第二个串的第一部份重复。第二个串的最后的部份"mo"跟第一个串的第一部份重复。所以"yzooo"跟"mo"都是这2个串的重复部份。其中,"yzooo"比较长,所以最长的重复部份的长度就是5。

非常简单的暴力做法,差点想用二分哈哈

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
string A,B;

bool check(int x){
    string pre=A.substr(0,x);
    string suf=B.substr(B.length()-x,x);
    if(pre==suf) return true;
    pre=B.substr(0,x);
    suf=A.substr(A.length()-x,x);

    if(pre==suf) return true;
    return false;
}

int main(){
    ios::sync_with_stdio();
    cin>>A>>B;
    int r=min(A.length(),B.length());
    for(int i=r;i>=0;i--){
        if(check(i)) {
            cout<<i;
            break;
        }
    }
    return 0;
}

5、租用游艇

简单dp题,坑的点在输入,n-1行分别代表i行到后面的所有点的距离

那么就很好想,从后往前遍历,更新当前点到n的距离为当前点到中间点的距离+中间点到n点的距离,答案就出来了

#include<iostream>
#include<algorithm>
using namespace std;
const int N=210;
int a[N][N],dp[N];
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int n;
    cin>>n;
    for(int i=1;i<n;i++){
        for(int j=i+1;j<=n;j++){
            cin>>a[i][j];
        }
        dp[i]=1e9;
    }
    for(int i=n-1;i>=1;i--){
        for(int j=i+1;j<=n;j++){
            dp[i]=min(dp[i],a[i][j]+dp[j]);
        }
    }
    cout<<dp[1];
    return 0;
}

6、shortest path of the king

中文题面:

国王独自一人在棋盘上。尽管他很孤独,但他并不会灰心,因为他有国家大事要做。例如,他必须对广场T进行正式访问。因为国王没有浪费时间的习惯,所以他想从目前的位置上尽量走最少的步数。请你帮他做这件事。

在一次移动中,国王可以到达有一个共同的边或一个共同的顶点的正方形上,(他通常可以移动到8个不同的方格上)。

输入格式

第一行包含方形s的棋盘坐标,第二行包含平方t。

棋盘坐标由两个字符组成,第一个是小写拉丁字母(从a到h),第二个是从1到8的数字。

输出格式

在第一行打印n - 国王移动的最小数量。然后在n行打印移动本身。每个移动用8:L,R,U,D,LU,LD,RU或RD中的一个来描述。

L,R,U,D分别针对左,右,上,下移动(根据图片),2字母组合代表对角线移动。如果答案不是唯一的,请打印其中的任何一个。

简单贪心

#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;

int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    char start[5];
    char end[5];
    cin>>start>>end;
    int subx=end[0]-start[0]; //获得x之间的距离,如果是负数,end在右边
    int suby=end[1]-start[1]; //获得y之间的距离,如果是负数,end在下边
    char tox=subx>0?'R':'L';
    char toy=suby>0?'U':'D';
    subx=abs(subx);
    suby=abs(suby);
    int dist=max(subx,suby);
    cout<<dist<<endl;
    while(subx||suby){
        if(subx) cout<<tox,subx--;
        if(suby) cout<<toy,suby--;
        cout<<endl;
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值