CSUFT2018年春季第二次个人赛 题解

CSUFT2018年春季第二次个人赛 题解

  1. A : A - A Very Hard Question
  2. B : Linear Algebra Test
  3. D : Dice Game
  4. E : The Architect Omar
  5. F : Building Numbers
  6. H : Eyad and Math
  7. I : Move Between Numbers
  8. K : Malek and Summer Semester
A : A Very Hard Question

并不想写题解,看懂题意就完事了

#include <bits/stdc++.h>


using namespace std;

int main()
{

    int T;
    scanf("%d",&T);
    while(T--) {
        int x,y;
        scanf("%d%d",&x,&y);
        printf("%d\n",x*100/(100+y));

    }
    return 0;
}
B : Linear Algebra Test

题目大意:就是给n个矩阵的行列情况,问哪些矩阵可以相乘。
解题思路:没别的,要加快查找的速度,所以使用map存储,找的很快。

#include <bits/stdc++.h>

using namespace std;
map<long ,long> row,col;

long long fun(long long a,long long b) {
    return a*b;
}
int main()
{
    //freopen("in.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        row.clear();
        col.clear();
        int n;
        scanf("%d",&n);
        int u,v;
        for(int i=0;i<n;i++) {
            scanf("%d%d",&u,&v);
            if(row.count(u)==0) row[u]=1;
            else row[u]++;
            if(col.count(v)==0) col[v]=1;
            else col[v]++;
        }
        long long sum=0;
          for(map<long,long>::iterator i=row.begin(); i!=row.end(); i++) {
            if(col.count(i->first)!=0)
                sum += fun(i->second,col[i->first]);
        }
        printf("%lld\n",sum);
    }
    return 0;
}
D : Dice Game

题目大意:给出骰子的六面,骰子没滚动一次加上朝上面的数字,问加到n,最少需要滚动多少步,每次骰子从1滚动,滚动只能有90°。
题目解析:小于12的点数可以直接搞定,大于12的点数,每次都1->5->6就可以最快,找找规律就好了。

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const int maxn=100005;

int a[25]={0,1,1,1,1,1,
            2,3,2,2,2,
            2,3,3,3,3,
            3,4,4,4,4,4,4};

int main()
{
//    freopen("in.txt","r",stdin);
    int T,n;
    scanf("%d",&T);
    int yu,bei;
    while(T--)
    {
        int ans=0;
        scanf("%d",&n);
        if(n==1)
            cout<<-1<<endl;
        else if(n<=11)
            cout<<a[n]<<endl;
        else if(n>11)
        {
            while(n>11){
                n-=11;
                ans+=2;
            }
            if(n==7)
                ans-=1;
            ans+=a[n];
            cout<<ans<<endl;
        }
    }
}



E : The Architect Omar

题目大意:题目给定了四个字符串,要在其他的字符串中找出来,并且只会出现在头几个字符。
题目解析:所以很简单的。匹配字符串,统计数量,按题目要求分类就好了。

#include <bits/stdc++.h>


using namespace std;
char str[3][10] = {"living","kitchen","bed"};
char s[55];
bool fun1(char *s1,char *s2) {
    int len = strlen(s2);
    if(strlen(s1)<len) return false;
    for(int i=0;i<len;i++) {
        if(s1[i]!=s2[i])
            return false;
    }
    return true;
}
int fun(){
    if(fun1(s,str[0]))
        return 1;
    if(fun1(s,str[1]))
        return 2;
    if(fun1(s,str[2]))
        return 3;

}
int main()
{
    //freopen("in.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--) {
        int n;
        scanf("%d",&n);
        int ans[3]={0,0,0};
        for(int i=0;i<n;i++) {
            cin>>s;
            switch(fun()) {
            case 1:ans[0]++;
            break;
            case 2:ans[1]++;
            break;
            case 3:ans[2]++;
            break;
            }
        }
        int minn  = ans[0];
        if(ans[1]<minn)
            minn = ans[1];
        if(ans[2]/2<minn)
            minn = ans[2]/2;
        printf("%d\n",minn);
    }
    return 0;
}
F : Building Numbers

题目大意:给T组输入,每组第一行给两个数字n和q,接下来是一行n个数字,,然后是q行的询问,每行询问两个数字,l和r,代表范围。n行数字的每一个数字可以有两种方式从1递增产生,如8可以1->2->4->8;如11可以1->2->4->8->9->10->11,但是有更快的方式1->2->4->5->10->11,只有五步就可以完成11的递增。所以找到给定的范围[l,r]内的数字最小的递增次数和。
解题思路
  第一的问题:对单个数字而言怎么才是最小的递增次数。答案是多乘2,所以对这个数字,我们尽可能的去除以2,不能除以2就要加以,倒过来考虑是最好的,这是因为在递增过程中,最接近目标数字的时候乘以二的增大效果是最明显的,所以格外的需要乘以二。因此倒过来考虑,n不断的除以二,不能除2的时候才减去1。这样子的接近速度明显是最优秀的。
  第二个问题,这个问题的解非常的需要时间,所以一般的解法会超时,因为不断地选择区间,导致白白的多求了很多遍重复的解。所以我们使用前缀和的技巧。比如对下列数: a 1 , a 2 , . . . , a i , . . . , a n a_1,a_2,...,a_i,...,a_n a1,a2,...,ai,...,an;我们假如用,计算出每一个 a i a_i ai的解 d i d_i di ,那么我们定义 s i s_i si ∑ k = 1 i d i \sum_{k=1}^{i}{d_i} k=1idi那么任意的区间段的和我们都可以用s的差来表示,如[l,r],等于 s r − s l − 1 s_r-s_{l-1} srsl1;这样子只需要 O ( n ) O(n) O(n)的时间复杂度就可以找到任意区间段的和。

#include <bits/stdc++.h>

using namespace std;
const int maxn = 1e5+5;
long long a[maxn],ans[maxn];

long long fun(long long a) {
    int ans=0;
    while(a>1) {
        if(a%2==0) a/=2;
        else       a--;
        ans++;
    }
    return ans;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--) {
        int n ,k;
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++) {
            scanf("%lld",&a[i]);
        }
        ans[0] = 0;
        for(int i=1;i<=n;i++)
            ans[i]=fun(a[i])+ans[i-1];
        int r,l;
        for(int i=0;i<k;i++) {
            scanf("%d%d",&r,&l);
            cout<<ans[l]-ans[r-1]<<endl;
        }


    }
    return 0;
}


H : Eyad and Math

题目大意:比较 a b a^b ab c d c^d cd谁比较大。
解题思路:直接算大小是不可能的,运算超时,所以两边同时取对数。再比较。

#include <bits/stdc++.h>

using namespace std;


int main()
{
    int T;
    scanf("%d",&T);
    int a,b,c,d;
    while(T--) {
        scanf("%d%d%d%d",&a,&b,&c,&d);
        double aa = log(a),cc = log(c);
        aa = aa*b;
        cc = cc*d;
        if(aa<cc)
            printf("<\n");
        else if(aa>cc)
            printf(">\n");
    }
    return 0;
}
K : Malek and Summer Semester

题目大意: 给一排数字大于50的是达标的,求达标率有没有达到给定的值。
解题思路:水货。

#include <bits/stdc++.h>

using namespace std;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--) {
        int n;
        double m;
        scanf("%d%lf",&n,&m);
        int sum=0,temp;
        for(int i=0;i<n;i++) {
            scanf("%d",&temp);
            if(temp>=50)
                sum++;
        }
        if((double)sum/n >m){
            cout<<"YES"<<endl;
        }else{
            cout<<"NO"<<endl;
        }
    }
    return 0;
}

其他的题目没有改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值