【题解】2019年广东工业大学腾讯杯新生程序设计竞赛(同步赛)

文章目录

  • A - 原初的信纸(水题)
  • B - 骑士的对决(水题)
  • C - 秘密的议会(水题)
  • D - 城市的税金(水题)
  • E - 缺席的神官(贪心+思维)
  • F - 失踪的玫瑰(思维)
  • G - 虚数的纸牌(模拟)
  • H - 绵羊的银币(斐波那契数列 + 规律)
  • I - 迷途的怪物(思维)
  • J - 简单的数学(数学)
  • K - 消亡的质数(数学)
  • M - 破碎的愿望(规律)


A - 原初的信纸(水题)

原题链接:https://ac.nowcoder.com/acm/contest/3036/A

  • 思路: 给数组从小到大排个序然后输出最后一个数即可。

Code(C++):

#include 
#include 
#include 
#include 
#include 
#define ll long long
using namespace std;
const int maxn=0x3f3f3f3f;
const int pi=acos(-1.0);
inline int read(){
    char c=getchar();    int num=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num;
}
int a[10010];
int main(){
    int t;    cin>>t;
    while(t--){
        int n;    cin>>n;
        for(int i=0;i<n;i++)
            cin>>a[i];
        sort(a,a+n);
        cout<<a[n-1]<<endl;
    }
}


B - 骑士的对决(水题)

原题链接:https://ac.nowcoder.com/acm/contest/3036/B

  • 思路: 简单模拟题,守卫骑士可以在两个武器中选,进攻骑士的武器是已知的,那么守卫骑士肯定会根据进攻骑士的武器在这两个武器中选个尽可能能赢,不输的。

Code(C++):

#include 
using namespace std;
const int maxn=0x3f3f3f3f;
const int pi=acos(-1.0);
inline int read(){
    char c=getchar();    int num=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num;
}
int main(){
    char a,b;    cin>>a>>b;
    char c;    cin>>c;
    if(c=='S'){
        if(a=='B' || b=='B')
            cout<<"pmznb"<<endl;
        else if(a=='S'||b=='S')
            cout<<"lyrnb"<<endl;
        else
            cout<<"ljrnb"<<endl;
    }
    else if(c=='J'){
        if(a=='S' || b=='S')
            cout<<"pmznb"<<endl;
        else if(a=='J'||b=='J')
            cout<<"lyrnb"<<endl;
        else
            cout<<"ljrnb"<<endl;
    }
    else{
        if(a=='J' || b=='J')
            cout<<"pmznb"<<endl;
        else if(a=='B'||b=='B')
            cout<<"lyrnb"<<endl;
        else
            cout<<"ljrnb"<<endl;
    }
    return 0;
}


C - 秘密的议会(水题)

原题链接:https://ac.nowcoder.com/acm/contest/3036/C

  • 思路: 遍历字符串,找出对应字符的数目,最后比较一下看看是否符合要求。

Code(C++):

#include 
using namespace std;
const int maxn=0x3f3f3f3f;
const int pi=acos(-1.0);
inline int read(){
    char c=getchar();    int num=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num;
}
int main(){
    int t;    cin>>t;
    while(t--){
        string str;
        cin>>str;
        int len = str.length();
        int sum1=0,sum2=0;
        for(int i=0;i<len;i++){
            if(str[i]=='Y' || str[i]=='y')
                sum1++;
            if(str[i]=='N' || str[i]=='n')
                sum2++;
        }
        if(sum1>=len/2)    cout<<"pmznb"<<endl;
        else if(sum2>=len/2)    cout<<"lyrnb"<<endl;
        else    cout<<"wsdd"<<endl;
    }
    return 0;
}


D - 城市的税金(水题)

原题链接:https://ac.nowcoder.com/acm/contest/3036/C

  • 思路: 这道题就是如果 q 等于1 就遍历相应区间计算结果,如果 q 等于2 就遍历相应区间,寻找相同数最多的那个数出现的次数。细节方面要处理好。

Code(C++):

#include 
#include 
#include 
using namespace std;
typedef long long ll;
ll p[105];
ll a[105];
int main(){
    int n,m;    cin>>n>>m;
    memset(p,0,sizeof(p));
    for(int i=1;i<=n;i++)
        cin>>p[i];
    while(m--){
        int q,l,r;	cin>>q>>l>>r;
        if(q==1){
            for(int i=l;i<=r;i++)
                p[i]=p[i]*251%996*404*123;
        }
        if(q==2){
            memset(a,0,sizeof(a));
            int k=1;
            for(int i=l;i<=r;i++)
                a[k++]=p[i];
            k--;
            sort(a+1,a+1+k);
            ll sum=1,ans=0;
            for(int i=2;i<=k;i++){
                if(a[i]==a[i-1])	sum++;
                else{
                    if(sum>ans)	ans=sum;
                    sum=1;
                }
            }
            if(sum>ans)	ans=sum;
            cout<<ans<<endl;
        }
    }
    return 0;
}


E - 缺席的神官(贪心+思维)

原题链接:https://ac.nowcoder.com/acm/contest/3036/E

  • 思路: 先把所给数组的间隔存入一个新数组,然后从小到大排序,遍历该数组到 1 ~ x-k+1,累加起来组后再加上 k 即可。

Code(C++):

#include 
#include 
using namespace std;
typedef long long ll;
ll a[2010];
ll b[2010];
int main(){
    ll n,m,k;    cin>>n>>m>>k;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    int x=1;
    for(int i=2;i<=n;i++)
        b[x++]=a[i]-a[i-1];
    x--;
    sort(b+1,b+1+x);
    int ans=0;
    for(int i=1;i<=x-k+1;i++)
        ans+=b[i];
    cout<<ans+k<<endl;
    return 0;
}


F - 失踪的玫瑰(思维)

原题链接:https://ac.nowcoder.com/acm/contest/3036/F

  • 思路: 思维题,要求一定能找到且次数最少的方案,那么我们就要考虑最差的情况,也就是尽量不要让我们找到的情况,那么一开始的玫瑰一定在边上,可以分为四种情况:

    • n == 1:直接输出 1 。

    • n == 2:直接取两次 1 ,为了使得字典序最小,所以不取 2,但测试了下,应该没有这个特胖样例。

    • n > 2 && n % 2 == 1:例如 n == 7,最差的情况是玫瑰一开始在 7 ,然后一直在 7 和 6 徘徊,这样我们得从 2 遍历到 6 ,找到 6 的时候花在 7 的盒子上,那么我们再遍历一遍,当再次找到 6 的时候花就一定在 6 的盒子上。自己多演算几遍就知道了。为什么玫瑰一开始不在 1 上呢,为了使得字典序最小嘛!

    • n > 2 && n % 2 == 0:例如 n == 6,最差的情况是玫瑰一开始在 1 ,然后一直在 1 和 2 徘徊,这样我们得从 2 遍历到 5,找到 5 的时候花在 2 的盒子上,然后再从 5 找到 2,找到 2 的时候就一定能找到花了。

    其实以上的思路就是通过紧逼,一次不行就再来一次,从而使得一定可以找到花。


Code(C++):

#include 
using namespace std;
int main() {
    int t;    cin >> t;
    while(t--) {
        int n;    cin>>n;
        if(n == 1)    cout << 1 << endl;
        else if(n == 2)    cout<< "2 2" <<endl;
        else if(n % 2 == 1) {
            for (int i = 2; i < n; i++)
                cout << i << " ";
            for (int i = 2; i < n; i++) {
                if (i != n-1)    cout << i << " ";
                else    cout << i <<endl;
            }
        }
        else if(n % 2 == 0) {
            for (int i = 2; i < n; i++)
                cout << i << " ";
            for (int i = n-1; i > 1; i--) {
                if (i != 2)    cout << i << " ";
                else    cout << i <<endl;
            }
        }
    }
    return 0;
}


G - 虚数的纸牌(模拟)

原题链接:https://ac.nowcoder.com/acm/contest/3036/G

  • 思路: 把每种牌存入数组并记录数量,分别计算每种出牌的方案数。

Code(C++):

#include 
#include 
#include 
#include 
#include 
#define ll long long
const int maxn=0x3f3f3f3f;
const int pi=acos(-1.0);
using namespace std;
inline int read(){
    char c=getchar();    int num=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num;
}
int p[20];
char str[20];
int main(){
    int t;    t=read();
    while(t--){
        memset(p,0,sizeof(p));
        cin>>str;
        for(int i=0;i<17;i++){
            if(str[i]>='3' && str[i]<='9')
                p[str[i]-'3']++;
            else if(str[i]=='0')
                p[7]++;
            else if(str[i]=='J')
                p[8]++;
            else if(str[i]=='Q')
                p[9]++;
            else if(str[i]=='K')
                p[10]++;
            else if(str[i]=='A')
                p[11]++;
            else    p[12]++;
        }
        int ans=0;
        for(int i=0;i<13;i++){
            ans+=p[i];
            if(p[i]>1)    ans+=p[i]*(p[i]-1)/2;
            if(p[i]==4)    ans++;
        }
        for(int i=0;i<13;i++){
            if(p[i]>=3){
                int cnt=0;
                for(int j=0;j<13;j++){
                    if(i!=j)    cnt+=p[j];
                }
                ans+=cnt*(p[i]==4?4:1);
            }
        }
        for(int i=0;i<13;i++){
            if(p[i]>=3){
                int cnt=0;
                for(int j=0;j<13;j++){
                    if(i!=j && p[j]==2)    cnt++;
                    else if(i!=j && p[j]==3)    cnt+=3;
                    else if(i!=j && p[j]==4)    cnt+=6;
                }
                ans+=cnt*(p[i]==4?4:1);
            }
        }
        for(int i=0;i+4<13;i++)
            ans+=p[i]*p[i+1]*p[i+2]*p[i+3]*p[i+4];
        cout<<ans<<endl;
    }
    return 0;
}


H - 绵羊的银币(斐波那契数列 + 规律)

原题链接:https://ac.nowcoder.com/acm/contest/3036/H

  • 思路: 这道题以 2 的幂次方从为区间不断递增,区间内都是一个相同的数,且区间其实就是斐波那契数列,所以只需要知道 n 是属于哪一个区间即可。

Code(C++):

#include 
#include 
#include 
#define ll long long
using namespace std;
inline int read(){
    char c=getchar();    int num=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num;
}
ll f[65],a[65];
int main(){
    f[0]=0;
    f[1]=1;
    for(int i=2;i<=60;i++)
        f[i]=f[i-1]+f[i-2];
    int t;    scanf("%d",&t);
    while(t--){
        ll n;    scanf("%lld",&n);
        ll q=(ll)1,cnt=0;
        while(q<=n){
            q*=2;
            cnt++;
        }
        printf("%lld\n",f[cnt]);
    }
    return 0;
}


I - 迷途的怪物(思维)

原题链接:https://ac.nowcoder.com/acm/contest/3036/I

  • 思路: p 是质数,那么 p - 1 肯定是合数。如果 n 是奇数的话,(p -1)^ n 对 p 取模,结果还是 p - 1;如果是偶数的话,结果就是 1 。

Code(C++):

#include 
using namespace std;
inline int read(){
    char c=getchar();    int num=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num;
}
typedef long long ll;
int main(){
    int t;    cin>>t;
    while(t--){
        ll p;    cin>>p;
        string n;    cin>>n;
        if((n[n.length()-1]-'0')%2)
            cout<<p-1<<endl;
        else    
            cout<<1<<endl;
    }
    return 0;
}


J - 简单的数学(数学)

原题链接:https://ac.nowcoder.com/acm/contest/3036/J

  • 思路: 这里运用到了 n 阶求导,数学渣渣的我,看一下大佬的推导过程。
    【题解】2019年广东工业大学腾讯杯新生程序设计竞赛(同步赛)_第1张图片
    所以只需要判断 n 的奇偶性即可直接输出结果。

Code(C++):

#include 
using namespace std;
typedef long long ll;
int main(){
    int t;    cin>>t;
    while(t--){
        ll n;    cin>>n;
        if(n&1)
            printf("%lld\n",n*(n+1));
        else  
            printf("%lld\n",-n*(n+1));
    }
    return 0;
}


K - 消亡的质数(数学)

原题链接:https://ac.nowcoder.com/acm/contest/3036/K

  • 思路: 立方差公式为 p = a3 - b3 = (a - b) (a2 + ab + b2),两个数的乘积本来应该是合数,但 p 确实质数,说明两个乘数中有一个为 1,可想而知 a - b = 1,那么 p = a2 + ab + b2,题目就变得简单了,只要枚举判断是否存在这样相邻的两个数的立方差等于 p。

Code(C++):

#include 
using namespace std;
typedef long long ll;
ll iscubicp(ll x){
    if(x<=0)    return 0;
    for(ll i=1;i*i+i*(i+1)+(i+1)*(i+1)<=x;i++)
        if(i*i+i*(i+1)+(i+1)*(i+1)==x)
            return 1;
    return 0;
}
int main(){
    int t;    cin>>t;
    while(t--){
        ll p;    cin>>p;
        if(iscubicp(p))    cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}


M - 破碎的愿望(规律)

原题链接:https://ac.nowcoder.com/acm/contest/3036/M

  • 思路: 该题数很大,要定义为 long long 型。由于字符串变化都是把字符串翻转后接到原字符串后面无限延伸,所以无限延伸的字符串只不过是所给字符串翻转后接到所给字符串得到的新字符串为循环节一直循环增加。我们只需要把 k 对所得到循环节字符串长度取余后输出相应位置的字符。

  • 注意: 有一个特判,如果取余后为 0,说明是最后一个字符。


Code(C++):

#include 
#include 
#include 
using namespace std;
typedef long long ll;
int main(){
    ll n,k;   
    cin>>n>>k;
    string s;    cin>>s;
    ll x=k%(n*2);
    string s1;
    s1=s;
    reverse(s1.begin(),s1.end());
    s=s+s1;
    if(x==0)    cout<<s[n*2-1]<<endl;
    else    cout<<s[x-1]<<endl;
    return 0;
}


你可能感兴趣的:(【题解】2019年广东工业大学腾讯杯新生程序设计竞赛(同步赛))