兰州大学第一届『飞马杯』程序设计竞赛(同步赛)

A.比赛新机制

题意:每道题目的罚时 s与比赛已经开始的时间(按分钟计) a 以及该题错误的提交次数(不包括编译错误) b 有关,即 s=a+b×20;Alice所有的题目提交一次便成功,有n 道题目。它可以从任意一道题目开始正序或者逆序完成,求最小的罚时数。

题解:对于正序,如果顺序为a1,a2,a3,......,an, 那么s1=n*a1+(n-1)*a2+(n-2)*a3+.......+2an-1+an;如果顺序为a2,a3,......,an,a1,那么s2=n*a2+(n-1)a3+......+2an+a1,s1-s2=(n-1)*a1-a2-a3-......-an=n*a1-sum;得si+1=si+sum-n*ai

对于逆序,如果顺序为an,an-1,......a3, a2, a1,sn=n*an+(n-1)an-1+......+a1;如果顺序为an-1,......a3, a2, a1,an,得sn-1=n*an-1+(n-1)an-2+***+2a1+an;si+1-si=n*ai+1-sum

每次递推更新最小值

反思:在数组得类型和声明位置错了好几次,大数组要定义在main函数外!同一代码,一会超时一会不超时的,还不知道为啥。

#include<bits/stdc++.h>
using namespace std;
#define MAXN 500010
#define NAF 1e18
typedef long long ll; 
ll a[MAXN];
//用int错,放main里错,找了好几遍!! 
int main(){
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    int n;
    while(t--){
        ll sum=0,minn=NAF,ans=0,reans=0;
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            sum+=a[i];
            ans+=(n-i+1)*a[i];
            reans+=i*a[i];
        }
        
        minn=min(reans,ans);
        //正序 
        for(int i=1;i<=n;i++){
            ans=ans+sum-n*a[i];
            minn=min(ans,minn);
        }
        //逆序 
        for(int i=n;i>=1;i--){
            reans=reans-n*a[i]+sum;
            minn=min(minn,reans);
        }
        cout<<minn<<endl;
    }
    return 0;
}

 
View Code

 

C.生命的游戏

题意:

题解:数据范围小,暴力模拟。

 

#include<bits/stdc++.h>
using namespace std;
#define MAXN 105
int s[MAXN][MAXN],s1[MAXN][MAXN],s2[MAXN][MAXN],n;
bool check(int a[][105],int b[][105]){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(a[i][j]!=b[i][j]){
                return false;
            }
        }
    }
    return true;
}
int sum(int x,int y){
    int x1,x2,y1,y2,cnt=0;
    x1=x-1,y1=y-1,x2=x+1,y2=y+1;
    if(x==1)    x1=n;
    if(y==1)    y1=n;
    if(x==n)    x2=1;
    if(y==n)    y2=1;
    if(s1[x1][y]==1)    cnt++;
    if(s1[x1][y1]==1)    cnt++;
    if(s1[x1][y2]==1)    cnt++;
    if(s1[x][y1]==1)    cnt++;
    if(s1[x][y2]==1)    cnt++;
    if(s1[x2][y1]==1)    cnt++;
    if(s1[x2][y]==1)    cnt++;
    if(s1[x2][y2]==1)    cnt++;
    
    return cnt;
}
int main(){
    int t;
    cin>>t;
    int k;
    while(t--){
        int flag=0,cnt=0;
        cin>>n>>k;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                cin>>s[i][j];
                s1[i][j]=s[i][j];
                s2[i][j]=s[i][j];
            }
        }
        while(k--){
            cnt++;
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    if(sum(i,j)==3){
                        s2[i][j]=1;
                    }else if(sum(i,j)<2||sum(i,j)>3){
                        s2[i][j]=0;
                    }else{
                        s2[i][j]=s1[i][j];
                    }
                }
            }
            
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    s1[i][j]=s2[i][j];    
                }
            }
            if(check(s,s2)){
                flag=1;
                break;
            }
        }
        if(flag==1){
            cout<<"YES"<<endl;
            cout<<cnt<<endl;
        }else{
            cout<<"NO"<<endl;
        }
    }
    return 0;
}
View Code

 

F.飞马分隔符

题意:子序列为原字符串中删去若干字符,剩余字符相对位置不变形成的序列。需要将这个字符串 s按顺序划分为若干部分s1,s2,,sk,且 s1+s2+⋯+sk=s(+ 表示字符串的连接),使得每一部分都不包含子序列FeiMa。而每次划分都需要一个“分隔符”,求至少需要多少分隔符。

题解:有多少子序列FeiMa就需要多少分隔符。从头到尾遍历,每次遇到字符 a ,判断前面是否顺次出现过一组 F、e、i、M,若出现过,则在此处分隔,更新答案,并清空记录。

 

#include<bits/stdc++.h>
using namespace std;
int main(){
    int t;
    cin>>t;
    int n,temp;
    string s,str="FeiMa";
    while(t--){
        int cnt=0;
        cin>>n;
        cin>>s;
        int flag=0;
        for(int i=0;i<n;i++){
            if(s[i]=='F'&&flag==0){
                flag+=1;
            }else if(s[i]=='e'&&flag==1){
                flag+=1;
            }else if(s[i]=='i'&&flag==2){
                flag+=1;
            }else if(s[i]=='M'&&flag==3){
                flag+=1;
            }else if(s[i]=='a'&&flag==4){
                cnt++;
                flag=0;
            }
        } 
        cout<<cnt<<endl;
    }
    return 0;
}
View Code

H.温暖的力量

题意:给一个数,求他最多能被分成几个素数。素数的个数大于1.无解输出-1,有解输出答案

题解:把这个数全部分成2和3.

#include<bits/stdc++.h>
using namespace std;
int main(){
    int t;
    cin>>t;
    int s;
    while(t--){
        cin>>s;
        if(s<=3){
            cout<<-1<<endl;
        }else{
            cout<<s/2<<endl;
        }
    } 
    return 0;
} 
View Code

 

J.翻滚吧硬币

题意:任取两枚硬币固定在二维平面上,并让它们恰好相切,用第三枚硬币沿着它们形成的边界进行翻滚,即时刻保证与至少一枚已固定的硬币相切。这样这枚运动的硬币在翻滚了一定的圈数之后,一定会回到原点,即恰好绕了一周。有三种情况,AB固定C运动;AC固定B运动;BC固定A运动。

题解:

 

 

#include<bits/stdc++.h>
using namespace std;
#define pi 3.1415926535897
int main(){
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    double r[3];
    double a,b,t1,t2,t3,s;
    while(t--){
        cin>>r[0]>>r[1]>>r[2];
        sort(r,r+3);
        t1=r[2]+r[0];
        t2=r[0]+r[1];
        t3=r[2]+r[1];
        a=acos((t1*t1+t2*t2-t3*t3)/(2*t1*t2));
        b=acos((t3*t3+t2*t2-t1*t1)/(2*t3*t2));
        s=2*(pi-a)*t1+2*(pi-b)*t3;
        printf("%.10f\n",s/(2*pi*r[2]));
    }
    return 0;
}
View Code

 

posted @ 2021-06-03 09:18  Endeavo_r  阅读(75)  评论(0)    收藏  举报