一月月赛题解

版权声明:本文为博主原创文章,可以随意转载。 https://blog.csdn.net/qq_32126633/article/details/79011990

赵子龙的 abcd

description
今天,赵子龙在愉快地刷题时,碰到了这样一道题:
给出非负正数a,b,c,d,求a+b+c+d;
赵子龙:????这么简单????
现在,就请你帮组赵子龙刷掉这道简单题吧。
input
第一行,测试数组组数T(T<100)
对于每一组数据,都有四个非负正数a,b,c,d(0<=a,b,c,d<=2^62)
output
a+b+c+d的值
simple input
2
0 0 0 0
1 1 1 1
simple output
0
4

当a,b,c,d都为 2^62次方时,ans才为2^64,这时可a=b=c=d=2^62,输出2^64对应的字符串;对于其他情况,unsigned long long 就可操作;
当然,用大整数是肯定可以的。

#include<iostream>
using namespace std;

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        unsigned long long a,b,c,d;
        cin>>a>>b>>c>>d;
        unsigned long long x=4611686018427387904;
        if(a==x&&b==x&&c==x&&d==x)
        {
            cout<<"18446744073709551616"<<endl;
        }
        else
        {
            cout<<a+b+c+d<<endl;
        }
    }
    return 0;
}

我,水题,来做

description
给你一个七位QQ号,输出小于这个QQ号的所有质数.
质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数。
input
单组数据
输入一个QQ号(七位QQ号,因为输出数据过多,样例比较小)
output
从小到大输出所有小于这个QQ号的质数,一行一个
simple input
20
simple output
2
3
5
7
11
13
17
19

这是一道素数筛裸题,最简单的筛法就是对于从小到大枚举每个数如果没有标记就是素数,
同时将他所有的倍数全都标记。核心代码:

for(int i=2;i<=n;i++){
    if(flag[i]==0){
        cnt++;
        for(int j=i*i;j<=n;j+=i)flag[j]=1;
    }
}
#include <cstdio>
#include <cstdlib>
#include<cstring>
using namespace std;
bool pri[10000000];
int main(){
    //freopen("out","w",stdout);
    //freopen("in","r",stdin);
    int n;
    while(~scanf("%d",&n)){
        //memset(pri,0,sizeof(pri));
        for (int i = 2; i <= n; i++)
        {
            if (!pri[i])
            {
                printf("%d\n", i);
                if ((long long)i * i > n)
                    continue;
                for (int j = i * i; j <= n; j += i)
                {
                    pri[j] = true;
                }
            }
        }
    }
    return 0;
}

猫吃鱼

description
世界上最幸福的事是什么?不过是猫吃鱼,狗吃肉,奥特曼打小怪兽。现有n只猫,m条鱼,每只猫都想尽可能多吃到鱼,但每只猫每次只能拿一条鱼,而且它们吃一条鱼所需的时间不同,吃的快的猫能更快地拿到鱼。问过了时间t完整的鱼有几条,不完整的鱼有几条。
input
第1行为测试数据数量
第2行为猫的数量n,鱼的数量m,时间t(n<=100,m<=5000,t<=1000)
第3行为每只猫吃一条鱼所需的时间a1,a2……an ( 0 < ai <= 2000 )
output
输出到t时刻完整鱼的数量p和不完整鱼的数量q 。p,q中间用一个空格隔开。
simple input
3
1 2 1
1
3 8 5
1 3 4
5 4 1
5 4 3 2 1
simple output
1 0
0 1
0 3

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int a[150];
int eat[150];

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(eat,0,sizeof eat);
        int n,sum,t;
        scanf("%d%d%d",&n,&sum,&t);
        for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
        sort(a+1,a+1+n);
        for(int i=1;i<=t;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(eat[j]==0&&sum>0)
                {
                    eat[j]++;
                    sum--;
                }
                else if(eat[j]>0)
                eat[j]++;
                eat[j]%=a[j];
            }
        }
        int left=0;
        for(int i=1;i<=n;i++)
        if(eat[i])left++;
        printf("%d %d\n",sum,left);
    }
    return 0;
}

分糖

description
有一个任务,需要A,B,C三人共同完成,A工作了a天,B工作了b天就已经把任务完成了,C觉得不好意思,于是拿出n颗糖让A和B分,该如何分给A、B较为合适呢?
input
有多组测试样例,每组数据仅一行,包含三个整数a,b,n(1<=a,b<=100,1<=n<=100000000)。(数据保证A、B都会得非负整数的钱)
output
对于每组数据,输出一个整数,即A应得糖果数。
simple input
5 4 90
8 4 123
simple output
60
123

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;

const ll MOD = 1000000009;
const int INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const db PI = acos(-1);
const db ERR = 1e-8;

int main() {
    int a, b, n;
    while (cin >> a >> b >> n) {
        db aver = (a + b) / 3;
        db ans = (a - aver) / aver * n;
        cout << ans << endl;
    }
    return 0;
}

Water Problem Again

description
Do you remember my two water problems? I hope you enjoyed them. This time,I will give you another one.
Drawing N horizontal lines and M vertical lines on a square paper.Then using scissors to cut lines.you can only cut a piece of paper at a time.
So how many times you should cut at least?
Input
Two positive integers N,M.
0< N,M<10^1000
Output
print the answer in a single line.
Sample Input
34641600153464160015 34641600153464160015
Sample Output
1200040461192488114771779609416453120255

纸片上A条横线B条竖线,每次只能剪一片纸,问至少剪多少次。

我们可以知道,最终纸片会被剪成(A+1)*(B+1)片,而每次剪纸片只会增加一片纸片,所以至少剪的次数为(A+1)*(B+1)-1.

py:
a,b=map(int,raw_input().split())

print((a+1)*(b+1)-1)

java:
import java.util.*;
import java.math.*;


public class Main{

    public static void main(String[] args){

        Scanner cin=new Scanner(System.in);

        BigInteger a,b,One=BigInteger.ONE,ans;

        a=cin.nextBigInteger();

        b=cin.nextBigInteger();

        System.out.println((a.add(One)).multiply(b.add(One)).subtract(One));

    }

}

mod

description
The is a BUCTer named Chicken Dish who has some strange ideas sometimes.Today,he is interested in math,and because it came to the end of the term.
So,he want to solve some problems to improve his development.
And his teacher asks him a question which he can not solve quickly,so,he came to you for help.
The problem description is: Give you a number a and some mod numbers n1,n2,…,wish you to find the answer of a%n1%n2….
input
The first line a number T,the test case number
the next is T test(s)
the first line a number n ,the number of n1,n2…
the next line is n numbers of n1,n2…
the next line is a number num of a
the last line is num numbers a1,a2,…anum
output
a test output num lines of num answer ans1,ans2….ansnum
simple input
1
4
10 9 5 7
5
14 8 27 11 25
simple output
4
3
2
1
0
hint
14%10%9%5%7=4
8%10%9%5%7=3
1<=n<=100000
1<=num<=100000
1<=ni<=1000000000
0<=ai<=1000000000

如果很多个数字对一个数字进行取模,第二个取模会把第一个取得模改变的数字,一定会比第一次取模得到的结果小,因此有效的取模的数字首先应该是递减的。这样,我们就可以在输入ai的时候,把无效的数字删除,留下一串递减的数组。
然后,最重要的一步,在数组中找到上次取模得到的结果比它小于或者等于的第一个数,然后用这个数字对上次得到的结果进行取模操作。
如果对每次向后面遍历一遍呢,遍历的时间复杂度是O(n),一共会输入m个数字,所以总的时间复杂度是O(mn),显然,在这种情况下无法满足时间要求。因此,为了能提高效率,只能在查找时进行优化,我们可以采用二分法,二分地来查找每次要找到的数字的位置,这样,查找的时间复杂度为O(log(n)),总的时间复杂度是O(m log(n)),可以在最坏的情况下在时间要求之内得到结果。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <stack>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
using namespace std;
long long num[100005];
int fin(int low, int high, int val)
{
    if (high - low <= 1)
        return low;
    int mid = (low + high) / 2;
    if (num[mid] <= val)
        fin(low, mid, val);
    else
        fin(mid, high, val);
}
int main()
{
    freopen("1.in","r",stdin);
    // freopen("1.out","w",stdout);
    int t;
    int n;
    int m;
    int i, j, k;
    int b;
    long long last;
    int coun;
    long long temp;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d", &n);
        scanf("%lld", &last);
        num[0] = last;
        coun = 1;
        for (i = 1; i < n; i++)
        {
            scanf("%lld", &temp);
            if (temp < last)
            {
                last = temp;
                num[coun] = last;
                coun++;
            }
        }
        scanf("%d", &m);
        for (i = 0; i < m; i++)
        {
            scanf("%d", &b);
            int x = 0;
            while (x < coun && b != 0)
            {
                b %= num[x];
                x = fin(x + 1, coun - 1, b);
            }
            printf("%d\n", b);
        }
    }
    return 0;
}

矩阵问题

description
一个r行c列的矩阵里的所有元素都为0或1,给出这个矩阵每一行的和以及每一列的和,那么是否存在这样一个矩阵满足条件呢,如果存在任意一个满足条件的矩阵则输出YES,如果不存在则输出NO
Input
每组测试数据第一行包含两个整数r,c,表示矩阵的行数和列数。
第二行包含r个32位无符号数,表示矩阵每行的和。
第三行包含c个32位无符号数,表示矩阵每列的和。
(1 <= r,c <= 100000)
output
如果存在这样的一个01矩阵,输出YES,否则输出NO。
simple input
1 1
0
1
1 1
1
1
simple output
NO
YES

首先需要判断行和列的总和是否相等,因为它们都应该是整个矩阵的所有元素之和。如果他们不相等则这个矩阵肯定不存在。
这道题的贪心策略是,把列和从大到小枚举,对每个列和,按行和从大到小的顺序进行选择填上1,然后该行的行和减去1.这种贪心策略之所以有效,是因为这种策略会使各行的行和趋向于平均,尽可能地使行和减为零的情况推迟发生,而行和减为零意味着,当前可选的行数减少1,因此后面的计算可选择方法肯定比这种贪心的策略要少。

#include<iostream>  
#include<cstdio>  
#include<cstring>  
#include<cstdlib>  
#include<cmath>  
#include<vector>  
#include<stack>  
#include<set>  
#include<map>  
#include<queue>  
#include<algorithm>  
using namespace std;  
int main(){
    //freopen("2.in","r",stdin); 
    int m,n;  
    int na,nb;  
    int ma,mb;  
    int a;  
    int sa,sb;  
    while(~scanf("%d %d",&m,&n)){  
        na=0;nb=0;  
        ma=0;mb=0;  
        sa=0;sb=0;  
        while(m--){  
            scanf("%d",&a);  
            if(a){  
                na++;  
                sa+=a;  
            }  
            if(a>ma)  
                ma=a;  
        }  
        while(n--){  
            scanf("%d",&a);  
            if(a){  
                nb++;  
                sb+=a;  
            }  
            if(a>mb)  
                mb=a;  
        }  
        if(sa!=sb||ma>nb||mb>na)  
            printf("NO\n");  
        else  
            printf("YES\n");  
    }  
    return 0;  
}  

马走日字

>
description
一次外出旅游,你路上遇到了一个骑着马的强盗,你很害怕,你需要找一条路跑回家B(n,m).地图类似一个矩阵,你在左上角A(0,0),你每次只可以走一步,可以选择向下走,也可以选择向右走。但是强盗所在的位置和强盗的马一次所能跳到的位置是不可以走过去的(强盗的马的移动方法与象棋中的马相同.请计算出从A点能够走到B点的所有路径条数。
input
首先输入一个整数t,代表有t组测试数据。
每组测试数据为四个整数,即B点的坐标(n,m)和强盗的坐标(x,y)。
1 < n,m < 20.
output
输出一个整数即路径的条数。
simple input
2
6 6 3 2
8 8 3 5
simple output
17
1393

首先说明一下,这个题搜索是做不出来的,复杂度太高,因此使用dp可以很快解出来

#include<iostream>  
#include<cstdio>  
#include<cstring>  
#include<cstdlib>  
#include<cmath>  
#include<vector>  
#include<stack>  
#include<set>  
#include<map>  
#include<queue>  
#include<algorithm>  
using namespace std;  
long long dp[100][100];  
bool Map[100][100];  
int main(){
    int kase;  
    scanf("%d",&kase);  
    int m,n;  
    int x,y;  
    int i,j,k;  
    while(kase--){  
        memset(Map,false,sizeof(Map));  
        memset(dp,0,sizeof(dp));  
        scanf("%d %d %d %d",&n,&m,&x,&y);  
        Map[x][y]=1;Map[x-2][y-1]=Map[x-2][y+1]=1;  
        Map[x+2][y-1]=Map[x+2][y+1]=1;  
        Map[x-1][y+2]=Map[x-1][y-2]=1;  
        Map[x+1][y+2]=Map[x+1][y-2]=1;  
        for(i=0;i<=n;i++)  
            if(Map[i][0]!=1)  
                dp[i][0]=1;  
            else  
                break;  
        for(i=0;i<=m;i++)  
            if(Map[0][i]!=1)  
                dp[0][i]=1;  
            else  
                break;  
        for(i=1;i<=n;i++){  
            for(j=1;j<=m;j++){  
                if(Map[i][j])  
                    dp[i][j]=0;  
                else  
                    dp[i][j]=dp[i-1][j]+dp[i][j-1];  
            }  
        }  
        printf("%lld\n",dp[n][m]);  
    }  
    return 0;  
}  

猜你喜欢

转载自blog.csdn.net/qq_32126633/article/details/79011990
今日推荐