中国地质大学(北京)第十四届大学生程序设计竞赛(上)

第一次写博客,有很多不足的地方请多见谅Orz

A.牛牛喜欢水果糖

牛牛天虽然是个男孩子,但是他最喜欢吃的零食就是水果糖了。

有一天,某商店推出了一款全新的水果糖,并且推出了一种新的优惠活动。

活动规则如下:

  • 牛牛天每吃一个糖果就会得到一张糖纸
  • 商店规定如果你可以拿 x 张糖纸换 ⌊​6/x⌋ 块全新的水果糖
  • ⌊a⌋ 的意思是 a 向下取整,比如 ⌊1.5⌋=1

因为牛牛天只知道吃吃吃,所以他一直攒着糖纸没有兑换,作为牛牛天的好朋友,在不购买新的糖果的情况下,你能帮他算算他最多能吃到多少颗糖果吗?

你需要回答 t 个独立样例。

思路:

  • 小学奥数题
  • 每次吃完一颗都会获得一个糖纸
  • 用一个while循环一直对当前糖纸数÷6直到糖纸数量少于6个,同时更新糖纸数
  • 向下取整没啥用233

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
const int mod=1e9+7;
int prime[maxn],vis[maxn];
int main(){
	int t;
	cin>>t;
	while(t--){
		ll x,ans=0;
		cin>>x;
		while(x>5){
			int te=x;
			ans+=x/6;
			x=te/6+te%6;
		}
		cout<<ans<<endl;
	}
	
}

B.The King Of Speed

题意:
给定一个长度不限的字符串(he–tui!),请输出Java中对应的数据类型
思路:
又是最讨厌的字符串,当看到数据范围会超过long long的时候就代表一定要使用字符串了。
首先先判断s[0]是否是-,然后判断长度是否超过19(+)/20(-),如果超过直接输出BigInteger。否则则将字符串转换为long long 保存判断大小。
代码(学长の快速解法):

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
    string s;
    cin>>s;
    if(s[0]=='-'){
        string tmp="-9223372036854775808";//string可以直接比较,很好用
        if(s.length()>20||s>tmp) return 0*puts("BigInteger");
    }
    else{
        string tmp="9223372036854775807";
        if(s.length()>19||s>tmp) return 0*puts("BigInteger");
    }
    ll ans=0,flag=1;
    for(auto it :s){
        if(it=='-')
            flag=-1;
        else{
            ans=ans*10+it-'0';
        }
    }
    ans*=flag;
    if(ans>=INT8_MIN&&ans<=INT8_MAX) return 0*puts("byte");
    if(ans>=INT16_MIN&&ans<=INT16_MAX) return 0*puts("short");
    if(ans>=INT32_MIN&&ans<=INT32_MAX) return 0*puts("int");
    if(ans>=INT64_MIN&&ans<=INT64_MAX) return 0*puts("long");
}

C.幸运数

如果一个数能被16整除或者通过重新排列这个数的各个位上的数字后能被16整除,那么这个数就是幸运数。你能判断这个数是幸运数吗?

题意:
判断一个各个位都不含0的数,通过重新排列是否能够成为16的倍数。

思路:
这个题在现场着实没啥思路(甚至脑洞了好一阵二进制)后来听可爱的学姐讲解后也是豁然开朗。
因为10000是16的倍数,所以大于10000的数字只需要判断后四位是否为16倍数即可。
ps:学到了一个新的函数next_permutation()可以获得组合的全排列(太好用了
具体整个链接:C++ STL中 next_permutation函数的用法
代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
string s;
bool check(){
    int num=0;
    for(auto it: s) num=num*10+it-'0';
    return num%16==0;
}
int main(){
    cin>>s;
    if(s.length()<=4){
        sort(s.begin(),s.end());
        do{
            if(check()) return 0*puts("Yes");
        }while(next_permutation(s.begin(),s.end()));
    }
    else {
        vector<int> cnt(15);
        for(auto it:s) cnt[it-'0']++;
        for(int i=1;i<=9;++i){
            for(int j=1;j<=9;++j){
                for(int k=1;k<=9;++k){
                    for(int l=1;l<=9;++l){
                        cnt[i]--,cnt[j]--,cnt[k]--,cnt[l]--;
                        if(cnt[i]<0||cnt[j]<0||cnt[k]<0||cnt[l]<0){
                            cnt[i]++,cnt[j]++,cnt[k]++,cnt[l]++;
                            continue;
                        }
                        if((i*1000+j*100+k*10+l)%16==0) return 0*puts("Yes");
                        cnt[i]++,cnt[j]++,cnt[k]++,cnt[l]++;
                    }
                }
            }
        }
    }
    puts("No");
    return 0;
}

D.牛牛天喜欢奇数

作为一名人生赢家,牛牛天满脑子都是些奇奇怪怪的东西。

有一天,牛牛天得到了一个所有元素都是正整数的矩阵,牛牛天有一个魔法棒,使用一次魔法棒可以让矩阵中的任何一个元素加1。

因为牛牛天非常喜欢奇数,所以他想让矩阵所有的行之和以及所有的列之和均为奇数。作为牛牛天的好朋友,你能告诉他最少使用几次魔法棒可以达到这个目标吗?
输入格式:
第一行是两个正整数 n,m (1≤n,m≤1000), 代表矩阵的行数和列数。
第二行到第 n+1 行每行包含 m 个正整数,代表矩阵的元素 a​ij​​ (1≤a​ij​​ ≤10​6​​ )。
输出格式:
如果牛牛天可以达到目标,请输出最少的使用魔法棒的次数,否则输出 -1。

思路:

赛场上为数不多的感觉比较简单的题

  • 每次对矩阵里的某一项+1的时候该项所在行列的奇偶性都会改变;
  • 统计有几行几列需要改变(和为偶数),如果abs(row-col)为奇数则无法得到想要的矩阵;
  • 所以答案为:
    abs(row-col)+max(row,col)-abs(row-col)=max(row,col);

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e3+5;
const int mod=1e9+7;
ll h[maxn],l[maxn],a[maxn][maxn];
int main(){
	ll n,m;
	cin>>n>>m;
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			cin>>a[i][j];
			h[i]+=a[i][j],l[j]+=a[i][j];
		}
	}
	ll row=0,col=0;
	for(int i=0;i<n;i++){
		h[i]=(h[i]+1)%2;//偶数为1 
		row+=h[i];
	}
	for(int j=0;j<m;j++){
		l[j]=(l[j]+1)%2;
		col+=l[j];
	}
	if(row==col){
		cout<<row;
		return 0;
	}
	if(abs(row-col)%2) cout<<-1;
	else cout<<max(row,col);
}

E.小小跟踪狂

敬请期待

F.坤坤逛超商

敬请期待

G.牛牛坤买手镯II

敬请期待

H.牛牛坤喜欢有趣的数

题目很简单,当一个质数为两个正整数的平方和时牛牛坤认为这个数是一个有趣的数,求不大于n的正整数中有多少个有趣的数?

输入格式:
第一行输入一个数字t表示t组样例。(1≤t≤10​5​​)
接下来t行每行一个正整数n。(1≤n≤2×10​7​)

输出格式:
输出t行,每行输出一个数字。

思路:
比赛前抄了欧拉筛的板子,但是在预处理的时候想法太简单(无语大遍历)一定会T,所以到最后也没写出来。考场上想了一些,最后结束学长一讲恍然大悟,我直接吐血Orz(还是太菜。

首先是除了2以外的素数都为奇数,若为有趣的数一定能拆成一个奇数平方与一个偶数平方数的和。然后很简单能想到,任何一个偶数的平方%4=0,任何一个奇数的平方%4=1。
所以只需要用欧拉筛的同时判断一下是否%4==1即可。

  • 注意如果不用快读或者不关流会T;
  • 用upper_bound(或前缀和)统计个数

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e7+5;
const int mod=1e6+7;
int cnt=0,ct=0;
vector<int> ans;
int prime[maxn],vis[maxn];
void prepare(int n);
int main(){
    std::ios::sync_with_stdio(false);
	prepare(maxn);
	ll t;
	cin>>t;
	while(t--){
		ll n;
		cin>>n;
		cout<<upper_bound(ans.begin(),ans.end(),n)-ans.begin()<<endl;
	}
	return 0;
}
void prepare(int n){
	int i,j;
    ans.push_back(2);
	for(i=2;i<=n;++i){
		if(!vis[i]){
            prime[++cnt]=i;
            if(i%4==1)
			ans.push_back(i);
		}
		for(j=1;j<=cnt;j++){
			int to=prime[j]*i;
			if(to>n) break;
			vis[to]=1;
			if(i%prime[j]==0) break;
		}
	}
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值