第13届景驰-埃森哲杯广东工业大学ACM程序设计大赛(回顾补题)

A 跳台阶

https://ac.nowcoder.com/acm/contest/90/A

规律为方法总数=2^\textup{(n-1)}

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        long long sum=0;
        sum=pow(2,n-1);
        printf("%lld\n",sum);
    }
    return 0;
}

B 跳一跳,很简单的

https://ac.nowcoder.com/acm/contest/90/B

知识盲区,待补

C 平分游戏

https://ac.nowcoder.com/acm/contest/90/C

比赛没写出来,赛后思路来源:https://www.cnblogs.com/jiachinzhao/p/8650297.html

代码实现中标注了细节

#include<bits/stdc++.h>
#define LL long long
#define P pair<int,int>
using namespace std;
const int N = 1e6 + 10;
int a[N],vis[N];
LL b[N];
int n, k;
LL cal(int cnt){
    b[cnt - 1] = 0;
    sort(b, b + cnt);
    return b[cnt / 2];
}
int main()
{
    cin>>n>>k;
    k = min(k, n - 1);
    LL sum = 0;
    for(int i = 0;i < n;i++){
        scanf("%d",a + i);
        sum += a[i];
    }
    if(sum % n ){
        puts("gg");
        return 0;
    }
    LL ans = 0, avg = sum / n;
    for(int i = 0;i < n;i++){
       if(!vis[i]){
            int j = i,cnt = 0;
            LL tmp = 0,p = 0;
            while(!vis[j]){
                vis[j] = 1;
                //b数组的值为a0+a1+...+an-(n+1)*avg
				//p的值表示为a0+a1+...+an-1-n*avg 
                b[cnt] = a[j] - avg + p, tmp += a[j];
                p = b[cnt++];
                //环上的数字求和 
                j = (j + k + 1) % n;
            }
            //tmp表示环上的数字总和,cnt为环上的数字个数 
            if(tmp % cnt || tmp / cnt != avg){
                puts("gg");
                return 0;
            }
            LL midnum = cal(cnt);
            for(int k = 0;k < cnt;k++) 
				ans += abs(midnum - b[k]);
        }
    }
    printf("%lld\n",ans);
    return 0;
}

D psd面试

https://ac.nowcoder.com/acm/contest/90/D

最长回文子序列,直接套板子。首先将字符串的大小写统一,最后的结果为数组的长度减去最长子序列的长度

#include<iostream>
#include<vector>
#include<cstring>
#include<string>
using namespace std;
int longestPalindromeSubSequence1(string str)
{
    int n=str.length();
    vector<vector<int> > dp(n,vector<int>(n));
    for(int j=0;j<n;j++){
        dp[j][j]=1;
        for(int i=j-1;i>=0;i--){
            if(str[i]==str[j])
                dp[i][j]=dp[i+1][j-1]+2;
            else
                dp[i][j]=max(dp[i+1][j],dp[i][j-1]);
        }
    }
    return dp[0][n-1];
}
int longestPalindromeSubSequence2(string str){
    int n=str.length();
    vector<vector<int> > dp(n,vector<int>(n));
    for(int i=n-1;i>=0;i--){
        dp[i][i]=1;
        for(int j=i+1;j<n;j++){
            if(str[i]==str[j])
                dp[i][j]=dp[i+1][j-1]+2;
            else
                dp[i][j]=max(dp[i+1][j],dp[i][j-1]);
        }
    }
    return dp[0][n-1];
}
int main()
{
    string s;
    int length;
    while(cin>>s)
    {
        for(int i=0;i<s.size();i++)
        {
            if(s[i]>='a'&&s[i]<='z')
                s[i]=s[i]-32;
        }
        length=longestPalindromeSubSequence2(s);
        cout<<s.size()-length<<endl;
    }
    return 0;
}

E 回旋星空

https://ac.nowcoder.com/acm/contest/90/E

一直在想先枚举i,再根据j枚举k,发现超时后想到在确定j枚举k的过程中使用二分,再然后就想不出了......

这里的正解思路为枚举中间节点j的数值,然后查找是否有两个长度相等的线段距离,最后结果数*2即为正确答案。在计算距离时没有开放,直接使用long long进行保存

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1011;
vector<long long> p[MAXN];
struct node{
    int x,y;
};
vector<node> q;
bool cmp(node a,node b) {
    if(a.x==b.x)
        return a.y<b.y;
    else
        return a.x<b.x;
}
long long distou(node a,node b) {
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
int main() {
    int t;
    scanf("%d",&t);
    while(t--) {
        int n;
        scanf("%d",&n);
        q.clear();
        for(int i=0;i<n;i++) {
            node temp;
            scanf("%d%d",&temp.x,&temp.y);
            q.push_back(temp);
        }
        if(n<=2) {
        	puts("WA");
        	continue;
		}
        sort(q.begin(),q.end(),cmp);
        for(int i=0;i<n;i++) {
            for(int j=0;j<n;j++) {
				long long sum1=distou(q[i],q[j]); 
                p[i].push_back(sum1);
            }
        }
        int cnt=0;
        for(int i=0;i<n;i++) {
            for(int j=0;j<n;j++) {
            	if(j!=i) {
                	long long ans=p[i][j];
                	for(int k=0;k<n;k++) {
                		if(k!=i&&ans==p[j][k])
                			cnt++;
					}
				}
            }
        }
        if(cnt!=0)
            printf("%d\n",cnt);
        else
            puts("WA");
    }
    return 0;
}

F 等式

https://ac.nowcoder.com/acm/contest/90/F

首先等式可以化简为 n(x+y)=xy 然后我就卡了......其实答案就在转角,在多化简一步后为  xy-n(x+y)=0

xy-n(x+y)+n^{2}=n^{2}   n(n-y)+x(y-n)=0  (x-n)(y-n)=n^{2}

对于n^{2}求解其因子个数即可得出答案

#include<bits/stdc++.h>
using namespace std;
//(x-n)*(y-n)==n*n
int main()
{
    int T,N;
    scanf("%d",&T);
    while(T--) {
        scanf("%d",&N);
        //求N*N的因数 
        int ans=1;
        for(int i=2;i*i<N;i++) {
            int temp=0;
            while(N%i==0) {
                temp++;
                N/=i;
            }
            ans*=(temp*2+1);
        }
        if(N>1) 
            ans*=3;//剩下一个大素数,则N^2有两个大素数,所以ans*(2+1) 
        printf("%d\n",(ans-1)/2+1);
    }
    return 0;
}

  G 旋转矩阵

https://ac.nowcoder.com/acm/contest/90/G

模拟题,使用cnt变量记录左转和右转的次数

#include<bits/stdc++.h>
using namespace std;
const int MAXN=50;
char s[MAXN][MAXN];
int main() {
    int t;
    scanf("%d",&t);
    while(t--) {
        int n,m;
        scanf("%d%d",&n,&m);
        getchar();
        for(int i=0;i<n;i++) {
            for(int j=0;j<m;j++)
                scanf("%c",&s[i][j]);
            getchar();
        }
        int cnt=0;
        string z;
        cin>>z;
        for(int i=0;i<z.length();i++) {
            if(z[i]=='L')
                cnt--;
            else
                cnt++;
        }
        if(cnt>=0)
            cnt%=4;
        else {
            while(cnt<0)
                cnt+=4;
            cnt%=4;
        }
        if(cnt==0) {
            printf("%d %d\n",n,m);
			for(int i=0;i<n;i++) {
                for(int j=0;j<m;j++)
                    printf("%c",s[i][j]);
                printf("\n");
            }
        }
        if(cnt==1){
            printf("%d %d\n",m,n);
			for(int i=0;i<m;i++) {
                for(int j=n-1;j>=0;j--) {
                    if(s[j][i]=='-')
                        printf("|");
                    else {
                        if(s[j][i]=='|')
                            printf("-");
                        else
                            printf("%c",s[j][i]);
                    }
                }
                printf("\n");
            }
        }
        if(cnt==2) {
        	printf("%d %d\n",n,m);	
            for(int i=n-1;i>=0;i--) {
                for(int j=m-1;j>=0;j--)
                    printf("%c",s[i][j]);
                printf("\n");
            }
        }
        if(cnt==3) {
        	printf("%d %d\n",m,n);
            for(int i=m-1;i>=0;i--) {
                for(int j=0;j<n;j++) {
                    if(s[j][i]=='-')
                        printf("|");
                    else {
                        if(s[j][i]=='|')
                            printf("-");
                        else
                            printf("%c",s[j][i]);
                    }
                }
                printf("\n");
            }
        }
        printf("\n");
    }
    return 0;
}

H 哲哲的疑惑

https://ac.nowcoder.com/acm/contest/90/H

比赛的时候也没写出来......数论只会GCD  在取模的过程中如果模数是素数,使用快速幂求取逆元求解

详情可参考这篇博客 https://www.cnblogs.com/YuXiaoze/p/11637793.html

#include<bits/stdc++.h>
using namespace std;
const long long mod=998244353;
long long n,m,l;
inline long long ksm(long long a,long long p) {
    long long re=1;
    while(p) {
        if(p&1)
            re=re*a%mod;
        p>>=1;
        a=a*a%mod;
    }
    return re;
}
inline long long C() {
    long long re=1,cmp=1;
    for(long long i=m+1;i<=n;i++)
        re=re*i%mod;
    for(long long i=2;i<=n-m;i++) 
        cmp=cmp*i%mod;
    return re*ksm(cmp,mod-2)%mod;
}
int main() {
    scanf("%lld%lld%lld",&n,&m,&l); // C(n,m)*(n-m)^l
    if(n<m)
        printf("0");
    else
        printf("%lld",ksm(n-m,l)*C()%mod);
    return 0;
}

I 填空题

https://ac.nowcoder.com/acm/contest/90/I

签到题

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
using namespace std;
int main()
{
    printf("ac\n");
    return 0;
}

J 强迫症的序列

https://ac.nowcoder.com/acm/contest/90/J

每次给n-1个元素加1,其实相当于每次给前n-1个小的数+1,直到所有的数字都为同一个和。那么可以将初始数组按照从小到大排序,然后每次只加前n-1个数进行模拟。再进一步想,对于n-1个小的数+1,相当于对最大数-1,每次都对序列中的最大数-1直至所有数相等,那么这个相等的数会是什么呢,没错就是原本的最小值。只需要在一开始将除了最小数的其他数字都减去最小数,求和,结果就是操作的步数。最终的结果就是最小值加上这个数值即为最终所有的数的结果。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
using namespace std;
int num[120000];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(num,0,sizeof(num));
        int n,sum=0,sum1=0;
        cin>>n;
        for(int i=0;i<n;i++)
        {
            cin>>num[i];
            sum+=num[i];
        }
        sort(num,num+n);
        for(int i=1;i<n;i++)
            sum1+=num[i]-num[0];
        printf("%d %d\n",sum1,num[0]+sum1);
    }
    return 0;
}

K 密码

https://ac.nowcoder.com/acm/contest/90/K

模拟

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
using namespace std;
const int maxn=10000000+100;
char s1[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,t1=0;
        cin>>n;
        scanf("%s",s1);
        //getchar();
        int len1=strlen(s1)-1;
        if(n==1)
            printf("%s\n",s1);
        else
        {
            int k1=2*(n-1);
            int sum1=0;
            while(sum1<=len1)
            {  
                printf("%c",s1[sum1]);
                sum1+=k1;
            }
            for(int i=1;i<(n-1);i++)
            {
                int k=2*(n-1-i);
                int k1=2*i;
                int sum=i;
                while(sum<=len1)
                {
                    printf("%c",s1[sum]);
                    sum+=k;
                    if(sum<=len1)
                        printf("%c",s1[sum]),sum+=k1;
                    else
                        break;
                }
            }
            k1=2*(n-1);
            sum1=n-1;
            while(sum1<=len1)
            {  
                printf("%c",s1[sum1]);
                sum1+=k1;
            }
            printf("\n");
        }
    }
    return 0;
}

L 用来作弊的药水

https://ac.nowcoder.com/acm/contest/90/L

可以直接暴力判定,使用对数判定是否相等即可

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        long long x,a,y,b;
        cin>>x>>a>>y>>b;
        if(fabs(a*log(x)-b*log(y))<1e-5)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}
发布了45 篇原创文章 · 获赞 1 · 访问量 6767

猜你喜欢

转载自blog.csdn.net/Ls_attack/article/details/104065065