广州大学ACM2021第七周训练 2021.04.13

广州大学ACM第七周训练

链接:GZHUACM第七周
闲话:开始记录的第一场训练赛。这场两点开始,当天补课(高数课旷不得)所以迟到了两个小时,不过前四题很友好,后面的写不了,所以其实也没差。(怎么还押韵了)我要丢掉百度的坏习惯。之前训练没有思路就百度一下题目类型往某个算法或者思维想,并且时不时百度算法模板。在这里提醒下自己,不能白白浪费这么好的机会。
那么就开始吧。

A - 1的个数(简单思维+二进制)

原题链接:计蒜客 - T1179
题意:一个十进制数输出二进制下1的个数。
题解:很简单暴力即可,由于二进制末位与奇偶对应,所以可以不断取奇偶和右移遍历每一个二进制位。

        // violet apricity
// Do all I can do.Do good to be good.

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<math.h>
#include<map>
#include<sstream>

#define STD using namespace std;
#define ll long long
#define db double
#define ldb long double
#define IOS std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0);
#define MAX 88888888
#define INF 0x3f
#define r0 return 0;
#define SYP system("pause");
#define endl '\n'



STD
int main()
{
    IOS
    ll a;
    cin>>a;
    ll ans=0;
    while (a)
    {
        if(a%2==1)ans++;
        a>>=1;
    }
    cout<<ans<<'\n';
    //SYP
    return 0;
}

B - 实数加法(大浮点数)

原题链接:B - 实数加法
题意:大浮点数相加,形如:ppppppp.qqqqqqq
题解:emmm怎么说呢,大数这玩意说难不难说简单不简单,一个对新手来说考验码力和细节的东西,第一次写是快八个月前了,先后写过好几次,到现在还是不够熟悉。鸿✌说建议学手java或者存个板子,是个好主意。

        // violet apricity
// Do all I can do.Do good to be good.

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<math.h>
#include<map>
#include<sstream>

#define STD using namespace std;
#define ll long long
#define db double
#define ldb long double
#define IOS std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0);
#define MAX 88888888
#define INF 0x3f
#define r0 return 0;
#define SYP system("pause");
#define endl '\n'


int a[1111],b[1111],len;
int main()
{
    IOS
    char x;
    std::string s1="",s3="",s2="",s4="";
    //来存下数字,注意整数部分要倒着存,因为是数组存运算时进位要方便
    //相反,因为相加方向不一样,小数不需要倒着存
    while(std::cin>>x&&x!='.')s1=x+s1;//存a整数部分
    std::cin>>s2;//存a小数部分
    while(std::cin>>x&&x!='.')s3=x+s3;//存b整数部分
    std::cin>>s4;//存b小数部分
    if(s1.length()<s3.length())swap(s1,s3);//先处理短的
    for(int i=0;i<s3.length();i++){//遍历短的相同部分相加
        a[i]+=s1[i]+s3[i]-2*'0';
        if(a[i]>=10)//进位
        {
            a[i+1]+=a[i]/10;
            a[i]%=10;
        }
    }
    for(int i=s3.length();i<s1.length();i++){//长的多出来那一部分
        a[i]+=s1[i]-'0';
        if(a[i]>=10)
        {
            a[i+1]+=a[i]/10;
            a[i]%=10;
        }
    }
    if(a[s1.length()]) len=s1.length();else len=s1.length()-1;
    //最后是否进位导致边长了一位
    //注意小数和整数相加的差异(方向相反)
    if(s2.length()<s4.length())swap(s2,s4);
    for(int i=0;i<s4.length();i++) b[i]=s2[i]+s4[i]-2*'0';
    for(int i=s4.length();i<s2.length();i++) b[i]=s2[i]-'0';
    for(int i=s2.length()-1;i>=0;i--){
        if(i==0&&b[i]>=10)//进位到个位去了
        {
            a[0]++;
            b[0]-=10;
        }
        else
        if(b[i]>=10)//还没进位到个位
        {
            b[i-1]++;
            b[i]-=10;
        }
    }
    int i=0;
    while(a[i]>=10){//小数相加的时候进了位要再处理一次整数进位
        a[i+1]++;
        a[i]-=10;
        i++;
    }
    len=std::max(len,i);//进位后改变长度
    for(int j=len;j>=0;j--)std::cout<<a[j];//输出整数部分
    std::cout<<'.';
    int d=0;
    for(int j=s2.length()-1;j>=0;j--)if(b[j]){d=j;break;}//后往前找到非0,即去掉后导0不输出
    for(i=0;i<=d;i++)std::cout<<b[i];//输出小数部分
    std::cout<<'\n';//OVER
    //SYP
    return 0;
}

C - 幂次方(递归+栈模拟)

原题链接:计蒜客 - T2103
题意:用括号的方式把一个非负整数用2的幂次方和表示。
题解:这和寒假在紫书上看的括号序列相比难度低了好多(根本比不了)。可以用栈模拟一下,大概就是:
1.solve(n)对n先取个log(2)得到temp,然后对内部分情况处理:
·若temp>2:说明内部还可以再分,先输出此时的2,再solve(temp)
·若temp==1:说明刚刚好,输出2结束了
·否则输出按正常输出2(temp)
2.然后处理外部:res=n-temp,若res>0说明外部还有,则:
输出+再solve(res)处理外部部分。

        // violet apricity
// Do all I can do.Do good to be good.

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<math.h>
#include<map>
#include<sstream>

#define STD using namespace std;
#define ll long long
#define db double
#define ldb long double
#define IOS std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0);
#define MAX 88888888
#define INF 0x3f
#define r0 return 0;
#define SYP system("pause");
#define endl '\n'




const int mod=10007;
void solve(ll n)
{
     int d=2;
     int cnt=0;
     int temp=log(n)/log(2);
     if(temp>2){
        std::cout<<"2(";
        solve(temp);
        std::cout<<")";
     }
     else if(temp==1){
        std::cout<<"2";
     }
     else {
        std::cout<<2<<"("<<temp<<")";
     }
     int res=n-(int)std::pow(2,temp);
     if(res>0){
        std::cout<<"+";
        solve(res);
     }
}
int main()
{
    IOS
    ll n;
    std::cin>>n;
    solve(n);
    std::cout<<'\n';
    //SYP
    return 0;
}

D - 新运算(模拟)

原题链接:计蒜客 - T1765
题意:定义了三种新运算符。输入一堆数轮流三种运算取模后输出结果。
题解:直接模拟即可。

        // violet apricity
// Do all I can do.Do good to be good.

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<math.h>
#include<map>
#include<sstream>

#define STD using namespace std;
#define ll long long
#define db double
#define ldb long double
#define IOS std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0);
#define MAX 88888888
#define INF 0x3f
#define r0 return 0;
#define SYP system("pause");
#define endl '\n'



STD
const int mod=10007;
int main()
{
    IOS
    ll n;
    cin>>n;
    ll cnt=0;
    ll ans=0;
    cin>>ans;
    n--;
    while(n--){
        ll x;cin>>x;
        if(cnt==0)ans=((ans*ans%mod)+(x*x%mod))%mod;
        else if(cnt==1)ans=((ans*ans%mod*ans%mod)%mod+x)%mod;
        else if(cnt==2)ans=(ans+(x*x%mod*x%mod)%mod)%mod;
        cnt++;
        cnt%=3;
    }
    cout<<ans<<'\n';
    //SYP
    return 0;
}

到此为止前四到简单题,下面的都是有点难度的,我只会写E,还是莫名其妙过的。

E - Subsequence

原题链接:计蒜客 - 38232
题意:给出一个母串和n个子串,判断子串是否位母串的子串。
题解:可以暴力过,也可以两个数组存个位置。
师兄题解是这么说的:序列自动机,就是找每个点右边的每个字符的位置。
我还不清楚自动机,记得好像写过类似的瞎搞就过了。
我的代码:

        // violet apricity
// Do all I can do.Do good to be good.

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<math.h>
#include<map>
#include<sstream>

#define STD using namespace std;
#define ll long long
#define db double
#define ldb long double
#define IOS std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0);
#define MAX 88888888
#define INF 0x3f
#define r0 return 0;
#define SYP system("pause");
#define endl '\n'



const int N=111111;
int a[100];
int b[100];
std::vector<int>ans;
const int mod=10007;
char s[N],c[N];
int has[N][130];
void pre(int x,int y)
{
    for(int i=0; i<130; i++)has[x][i]=has[x+1][i];
    has[x][y]=x;
}
int main()
{
    IOS
    std::cin>>s;
    int n;
    std::cin>>n;
    int len=strlen(s);
    memset(has,-1,sizeof(has));
    for(int i=len-1; i>=0; i--)
    {
        int x=(int)s[i];
        pre(i,x);
    }
    while(n--)
    {
        std::cin>>c;
        int temp=strlen(c);
        int i=0,j=0;
        for(j=0; j<temp; j++)
        {
            int x=(int)c[j];
            int y=has[i][x];
            if(y<i)break;
            i=y+1;
        }
        if(j>=temp)std::cout<<"YES\n";
        else std::cout<<"NO\n";
    }
    //SYP
    return 0;
}

师兄的代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
char s[100010],t[1010];
int nxt[100010][26];
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>s+1;
    int n=strlen(s+1);
    //建序列自动机
    for(int i=0;i<26;i++) nxt[n][i]=n+1;
    for(int i=n-1;i>=0;i--){
        for(int j=0;j<26;j++)
         nxt[i][j]=(s[i+1]=='a'+j?i+1:nxt[i+1][j]);
    }
    int m;
    cin>>m;
    while(m--){
      cin>>t+1;
      int len=strlen(t+1);
      int i=0,j=0;
      while(i<len+1){
        j=nxt[j][t[i]-'a'];
        if(j==n+1) break;
        i++;
      }
      if(i==len+1) cout<<"YES"<<'\n';
      else cout<<"NO"<<'\n';
    }
}

下面的暂时不会啦,留着以后补吧。
>_<
じゃ、またね

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
中山大学ACM模板.pdf是中山大学ACM竞赛队所编写的一个模板文档,用于帮助队员们在ACM竞赛中快速地编写程序。该模板包含了常见的算法和数据结构的实现代码,以及一些常见的技巧和优化方法的示例。 模板中包括的一些常用的算法有:排序算法(如快速排序、归并排序)、搜索算法(如深度优先搜索、广度优先搜索)、图论算法(如最短路径算法、最小生成树算法)、动态规划算法等等。这些算法是ACM竞赛中经常会用到的基本技巧。 此外,模板还包含了一些常见的数据结构的实现代码,如栈、队列、堆、并查集等等。这些数据结构可以在解决问题的过程中帮助队员们高效地组织和管理数据。 模板中还涵盖了一些常见的编程技巧和优化方法,用于提高程序的效率和减少运行时间。例如,位操作、离散化、约瑟夫问题的优化等等。 中山大学ACM模板.pdf的编写,参考了ACM竞赛中常见的考点和题型,对每个算法和技巧都给出了详细的解释和示例代码,方便队员们学习和理解。同时,该模板还提供了一些习题和题解,供队员们进行练习和思考。 总之,中山大学ACM模板.pdf是中山大学ACM竞赛队为了提高队员们在ACM竞赛中的编程水平和解题能力而编写的一个非常有用的参考资料。通过学习和使用这个模板,队员们可以更加快速、高效地解决ACM竞赛中遇到的各类问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值