2020上海高校程序设计竞赛暨第18届上海大学程序设计联赛夏季赛(同步赛)

A.同源

题目大意:gcd(a,b)=gcd(a,c)=gcd(b,c)=k,a+b+c=n,给出n,k,构造a,b,c(a,b,c!=k)。1<=n,k<=10^18

题解:思维+构造 因为gcd(a,b)=gcd(b,c)=gcd(a,c)=k.说明a,b,c都为k的倍数,设a=x*k,b=y*k,c=z*k,a+b+c=x*k+y*k+z*k=(x+y+z)*k=n.所以x+y+z=n/k.并且gcd(x,y)=1,gcd(x,z)=1,gcd(y,z)=1,x,y,z!=1

代码:

#include
#include
#include
#include
#define LL long long
using namespace std;

int T;

LL n,k;

LL gcd(LL x,LL y)
{
    return y==0?x:gcd(y,x%y);    
}
 
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld",&n,&k);
        if(n%k) 
        {
            cout<<"-1 -1 -1\n";
            continue;
        }
        n=n/k;
        bool flag=false;
        for(LL i=2;i<=10;i++)
        {
            for(LL j=2;j<=10;j++)
            {
                LL gg=n-i-j;
                if(gg<2) break;
                if(gcd(i,gg)==1&&gcd(i,j)==1&&gcd(j,gg)==1)
                {
                    cout<" "<" "<endl;
                    flag=true;
                    break;
                }
            }
            if(flag) break;
        }
        if(!flag) cout<<"-1 -1 -1\n";
    }
    return 0;
}
View Code

 


 

B.分子

题目大意:有机分子只能由 C, H, O 三种元素组成。根据珂学家们的探测,一个 C 原子的式量为 13 ,一个 H 原子的式量为 1 ,一个 O 原子的式量为 17 。一个有机分子的式量恰为各个原子的式量的总和。给出分子式,求分子式量。

题解:字符串模拟+栈 具体解释见代码

代码:

#include
#include
#include
#include
#include
#define LL long long
using namespace std; 

int a[20];
bool flag=false;
stackst;

int main()
{
    string s;
    cin>>s;
    int len=s.length();
    LL ans=0; 
    a['C'-'A']=13;a['H'-'A']=1;a['O'-'A']=17;
    for(int i=0;i)
    {
        if(s[i]=='(') flag=true,st.push(-1);//现在在括号里,入栈-1 
        if((s[i]=='H'||s[i]=='C'||s[i]=='O')&&flag&&(s[i+1]<'1'||s[i+1]>'9')) st.push(a[s[i]-'A']);//在括号里后一位不是数字直接入栈 
        if(flag==false&&(s[i]=='C'||s[i]=='H'||s[i]=='O')&&(s[i+1]<'1'||s[i+1]>'9')) ans+=a[s[i]-'A'];
        //没在括号里,并且后一位不是数字,直接计入答案
        //没在括号里,并且后一位是数字,统计 
        if(flag==false&&(s[i]=='C'||s[i]=='H'||s[i]=='O')&&(s[i+1]>='0'&&s[i+1]<='9'))
        {
            LL temp=a[s[i]-'A'],js=0;
            i++;
            while(s[i]>='0'&&s[i]<='9')
            {
                js=js*10+s[i]-'0';
                i++;
            }
            ans=ans+temp*js;
            i--;
        }  
        //在括号里,并且后一位是数字,累加 
        if(flag==true&&(s[i]=='C'||s[i]=='H'||s[i]=='O')&&(s[i+1]>='0'&&s[i+1]<='9'))
        {
            LL temp=a[s[i]-'A'],js=0;
            i++;
            while(s[i]>='0'&&s[i]<='9')
            {
                js=js*10+s[i]-'0';
                i++;
            }
            i--;
            st.push(js*temp); 
        }
        //右括号,出栈累加 
        if(s[i]==')')
        {
            flag=false; 
            LL temp=0;
            while(1)
            {
                LL x=st.top();st.pop();
                if(x==-1) break;
                temp=temp+x; 
            }
            if((s[i+1]>='0'&&s[i+1]<='9')) 
            { 
               i++;
               LL js=0;
               while(s[i]>='0'&&s[i]<='9')
               {
                js=js*10+s[i]-'0';
                i++;
               }
            // cout<
               i--;
               ans=ans+temp*js;
             }else ans=ans+temp;
        }
    }
    cout<endl;
    return 0;
}
//CH3(CH2)10CH3
//H(HH)C(CH2)3O(H)1 
View Code

 


 

C.爵士

题目大意:查询字符串里有无字符‘2’

题解:签到题

代码:

#include
#include
#include
#include
using namespace std;
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int n,nn=0;
        cin>>n;getchar();
        for(int i=1;i<=n;i++)
        {
            string s;
            getline(cin,s);
            int len=s.length();
           // cout<
            for(int j=0;j)
            {
                if(s[j]=='2')
                {
                    nn++;
                    break;
                }
            }
        }
        printf("%.10lf\n",1.*nn/n);
    }
    return 0;
}
View Code

 


 

 

D.内存

题目大意:一个模拟。。。

题解:我先鸽了。。。

代码:

 


 

F.游戏

题目大意:博弈。每轮选择树上一条边,收益为边两侧节点中较小的数量,不能取时,分数多的获胜。

题解:发现先手必赢。解释。


 

 

G.选择

题目大意:从n个数中选择n/2(向下取整),且第x个数必须选,并且不能选择相邻的数,求n/2个数的和的最大值。

题解:DP  dp[i]表示1--i 选择i/2的数的最大值,因为第x个数必须选择,给a[x]+=INF,这样就保证在转移时第x个数一定会被取到。

sum[i]为1--i,奇数位的数的前缀和。

i为奇数时,dp[i]=max(dp[i-1],dp[i-2]+a[i]) (前者为不选,后者为选)

i为偶数时,dp[i]=max(sum[i-1],dp[i-2]+a[i])(前者为不选,后者为选)

ps:#define INF (1e16)就错...;n;(再也不用define了;n;)INF为1<<30也不对 举个极端数据就懂了

代码 

#include
#include
#include
#include
#define N 200009
#define LL long long
using namespace std;
const LL INF=1e16;

int n,x;

LL a[N],sum[N],dp[N];

LL read()
{
    LL x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}


int main()
{
    n=read();x=read();
    for(int i=1;i<=n;i++)
    {
        a[i]=read();
//        cout<
    }    
    a[x]+=INF; sum[1]+=a[1];
    for(int i=3;i<=n;i+=2)
    {
        sum[i]=sum[i-2]+a[i];
    }
    for(int i=2;i<=n;i++)
    {
        if(i&1)
        {
            dp[i]=max(dp[i-1],dp[i-2]+a[i]);
        }else
        {
            dp[i]=max(sum[i-1],dp[i-2]+a[i]);
        }
    }
    //cout<
    cout<INF; 
    return 0;
} 
View Code

 

你可能感兴趣的:(2020上海高校程序设计竞赛暨第18届上海大学程序设计联赛夏季赛(同步赛))