牛客周赛_Round76_abcdef

比赛链接

Round76

A 小红出题

题目描述

小红每周一到周五上班,工作日每天都要出 3 3 3 道题目。
已知小红入职当天为星期一,并且已经在职 n n n 天。
请问她总共出了几道题目?
第一行有一个整数 n   (   1 ≤ n ≤ 1 0 3   ) n\ (\ 1 \leq n \leq 10^3\ ) n ( 1n103 )

题解

算出经历了多少个完整的星期。然后算出剩下多少天,进行相加。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'

void solve()
{
	int n;
	cin>>n;
	int x=n/7;
	int ans=x*15;
	n%=7;
	if(n>=5) n=5;
	ans+=n*3;
	cout<<ans<<endl;
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t=1;
	//cin>>t;
	while(t--) solve();
}
n=int(input())
x=n//7
ans=x*15
n%=7
if n>=5: n=5
ans+=n*3
print(ans)

B 串串香

题目描述

给定一个长度为 n n n ,仅包含小写字母的字符串 s s s
请你构造出一个非空字符串 t t t ,使得它在 s s s 中作为子串出现的次数最多。
子串是指,从原字符串中连续截取一些字符,得到的新字符串。
第一行有一个整数 n   (   1 ≤ n ≤ 1 0 5   ) n\ (\ 1 \leq n \leq 10^5\ ) n ( 1n105 )
第二行有一个字符串 s s s ,字符串仅包含小写字母。

题解

出现次数最多的字符串一定可以用单个字母表示,因为假设 a b ab ab为所求答案,那么 a a a出现的次数一定会大于等于 a b ab ab的次数(会有零散的 a a a)。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'

void solve()
{
	int n;
	cin>>n;
	string s;
	cin>>s;
	map<char,int> mp;
	for(int i=0;i<n;i++){
		mp[s[i]]++;
	}
	char a;
	int maxx=0;
	for(auto i:mp){
		if(i.second>maxx){
			maxx=i.second;
			a=i.first;
		}
	}
	cout<<a<<endl;
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t=1;
	//cin>>t;
	while(t--) solve();
}
n=int(input())
s=input()
mp={}
for i in range(n):
    mp[s[i]]=mp.get(s[i],0)+1
a=''
maxx=0
for k,v in mp.items():
    if v>maxx:
        maxx=v
        a=k
print(a)

C 小红的gcd

题目描述

小红有一个长度为 n n n 的数组,她希望数组元素之和越少越好。
她可以进行任意次操作,每次选择数组中的两个元素 a i a_i ai a j a_j aj ,令 a i = a j = gcd ⁡ ( a i , a j ) a_i=a_j=\gcd(a_i,a_j) ai=aj=gcd(ai,aj)
所有操作结束后,请你输出最小的数组元素之和。
第一行有一个整数 n   (   1 ≤ n ≤ 1 0 5   ) n\ (\ 1 \leq n \leq 10^5\ ) n ( 1n105 )
第二行有 n n n 个整数 a i   (   1 ≤ a i ≤ 1 0 9   ) a_i\ (\ 1 \leq a_i \leq 10^9\ ) ai ( 1ai109 )

题解

对俩个数进行操作后,结果是小于等于之前的俩个数的。且可以无限次的操作。那么最终答案一定是对所有数俩俩进行一次操作。最后所有数都会变为 g c d ( a 1 , a 2 . . . . a n ) 。 gcd(a_1,a_2....a_n)。 gcd(a1,a2....an)

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
const int N=1e5+10;
int a[N];

void solve()
{
	int n;
	cin>>n;
	int f;
	cin>>f;
	for(int i=2;i<=n;i++){
		cin>>a[i];
		f=__gcd(a[i],f);
	} 
	cout<<n*f<<endl;
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t=1;
	//cin>>t;
	while(t--) solve();
}
import math
n=int(input())
f=int(input())
a=[0]*(n+1)
for i in range(2,n+1):
    a[i]=int(input())
    f=math.gcd(a[i],f)
print(n*f)

D 奇偶调整

题目描述

小红有一个长度为 n n n 的数组 a a a ,第 i i i 个元素为 a i a_i ai
小红可以执行两种操作,操作内容如下:
1.选择一个偶数元素 a i a_i ai ,令 a i = a i / 2 a_i=a_i/2 ai=ai/2
2.选择一个奇数元素 a i a_i ai ,令 a i = a i ⊕ 1 a_i=a_i \oplus 1 ai=ai1
其中,操作 1 1 1 最多执行 m m m 次,操作 2 2 2 最多执行 k k k 次。
小红想最小化数组元素之和,请你输出这个值。
⊕ \oplus 代表按位异或。
第一行有三个整数 n   (   1 ≤ n ≤ 1 0 5   ) n\ (\ 1 \leq n \leq 10^5\ ) n ( 1n105 ) m   (   1 ≤ m ≤ 1 0 9   ) m\ (\ 1 \leq m \leq 10^9\ ) m ( 1m109 ) k   (   1 ≤ k ≤ 1 0 9   ) k\ (\ 1 \leq k \leq 10^9\ ) k ( 1k109 )
第二行有 n n n 个整数 a i   (   1 ≤ a i ≤ 1 0 9   ) a_i\ (\ 1 \leq a_i \leq 10^9\ ) ai ( 1ai109 )

题解

操作1即为将一个偶数除二,操作二为将一个奇数减一。所以贪心的想,每次对最大的数进行操作,如果为奇数,操作1,2都有次数,则可以让他减一变为偶数后进行操作1。如果为偶数,则进行操作2。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
const int N=1e5+10;
int aa[N];

void solve()
{
	int n,m,k;
	cin>>n>>m>>k;
	priority_queue<int> q;
	for(int i=1;i<=n;i++){
		int x;
		cin>>x;
		q.push(x);
	}
	int ans=0;
	while(q.size()){
		int t=q.top();
		q.pop();
		int tt=t;
		if(t%2){
			if(k && m){
				t-=1;
				t/=2;
				k--;
				m--;
			}else if(k){
				t-=1;
				k--;
			}
		}else{
			if(m){
				t/=2;
				m--;	
			}
		}
		if(t==tt){
			ans+=t;
		}else{
			q.push(t);
		}
	}
	cout<<ans<<endl;
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t=1;
	//cin>>t;
	while(t--) solve();
}
import heapq
n,m,k=map(int,input().split())
q=[]
for _ in range(n):
    x=int(input())
    heapq.heappush(q, -x)
ans=0
while q:
    t=-q[0]
    heapq.heappop(q)
    tt=t
    if t%2:
        if k and m:
            t-=1
            t//=2
            k-=1
            m-=1
        elif k:
            t-=1
            k-=1
    else:
        if m:
            t//=2
            m-=1
    if t==tt:
        ans+=t
    else:
        heapq.heappush(q, -t)
print(ans)

E 幂次进近

题目描述

给定 t t t 次询问,每次询问给出两个正整数 n n n k k k
请你找到最小的正整数 m m m ,使得 n − m k n-m^k nmk绝对值最小。
第一行有一个整数 t   (   1 ≤ t ≤ 1 0 5   ) t\ (\ 1 \leq t \leq 10^5\ ) t ( 1t105 )
随后 t t t 行,每行两个整数 n , k   (   1 ≤ n , k ≤ 1 0 18   ) n,k\ (\ 1 \leq n,k \leq 10^{18}\ ) n,k ( 1n,k1018 )

题解

先进行特判,若k超过了60,直接输出1,因为 2 60 已经到达了 1 e 18 的级别。 2^{60}已经到达了1e18的级别。 260已经到达了1e18的级别。进行二分查找,找到最大的 m m m使满足 n − m k n-m^k nmk大于等于 0 0 0。再将 m m m m + 1 m+1 m+1计算的结果进行比较,取较小的。本题需要注意的是由于n,k都比较大,需要使用__int128。

本题和cf一场div4的E题比较像:相似题目推荐

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define lll __int128
int n,k;

lll qmi(lll a,lll b)
{
	lll ans=1;
	while(b){
		if(b&1) ans=ans*a;
		b>>=1;
		a=a*a;
	}
	return ans;
}

bool check(lll x){
	lll ans=1;
	for(int i=1;i<=k;i++){
		ans*=x;
		if(ans/n>=1) return 0;
	}
	return 1;
}

void solve() 
{
	cin>>n>>k;
	if(k>60){
		cout<<1<<endl;
		return;
	}
	if(k==1){
		cout<<n<<endl;
		return;
	}
	lll l=1,r=n;
	while(l<r){
		lll mid=l+r+1>>1;
		if(check(mid)) l=mid;
		else r=mid-1;
	}
    int ans=l;
	if(n-qmi(l,k)<qmi(l+1,k)-n) cout<<ans<<endl;
	else cout<<ans+1<<endl;
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t=1;
	cin>>t;
	while(t--) solve();
} 
def qmi(a,b):
    ans=1
    while b:
        if b&1: ans*=a
        b>>=1
        a*=a
    return ans

def check(x):
    ans=1
    for i in range(1,k+1):
        ans*=x
        if ans//n>=1: return False
    return True

n,k=map(int,input().split())
if k>60:
    print(1)
else:
    if k==1:
        print(n)
    else:
        l,r=1,n
        while l<r:
            mid=(l+r+1)>>1
            if check(mid): l=mid
            else: r=mid-1
        ans=l
        if n-qmi(l,k)<qmi(l+1,k)-n: print(ans)
        else: print(ans+1)

F 同位序列

题目描述

定义 f ( x ) f(x) f(x) x x x 在二进制表示下的 1 1 1 的个数。
例如 f ( 7 ) = 3 f(7)=3 f(7)=3 f ( 8 ) = 1 f(8)=1 f(8)=1 f ( 9 ) = 2 f(9)=2 f(9)=2
定义 g ( x ) g(x) g(x) 为 第一个比 x x x 大的数字 y y y ,使得 f ( x ) = f ( y ) f(x)=f(y) f(x)=f(y)
例如 g ( 1 ) = 2 g(1)=2 g(1)=2 g ( 2 ) = 4 g(2)=4 g(2)=4 g ( 3 ) = 5 g(3)=5 g(3)=5
给你一个长度为 n n n 的数组 a a a ,第 i i i 个元素为 a i a_i ai
我们希望从数组 a a a 中挑选出一些元素,构造一个长度为 m m m 的同位序列 b b b
同位序列 满足如下条件:
对于所有的 j ∈ [ 2 , m ] j \in [2,m] j[2,m] ,都有 b j = g ( b j − 1 ) b_j=g(b_{j-1}) bj=g(bj1)
当然,同位序列越长越好,请你最大化其长度 m m m ,然后输出 m m m 和对应的同位序列。
如果有多解,输出任意一个即可。
第一行有一个整数 n   (   1 ≤ n ≤ 1 0 5   ) n\ (\ 1 \leq n \leq 10^5\ ) n ( 1n105 )
第二行有 n n n 个整数 a i   (   1 ≤ a i ≤ 1 0 9   ) a_i\ (\ 1 \leq a_i \leq 10^9\ ) ai ( 1ai109 )

题解

先处理出每个数的给 g ( x ) g(x) g(x)。然后用map处理最长长度。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define lll __int128
const int N=1e5+10,M=32;
int a[N];

void solve() 
{
	int n;
	cin>>n;
	map<int,int> g;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		vector<int> bit(M);
		for(int j=0;j<M;j++){
			if(a[i]>>j&1) bit[M-j-1]=1;
		}
		next_permutation(bit.begin(),bit.end());
		for(int j=0;j<M;j++){
			if(bit[M-j-1]) g[a[i]]|=1<<j;
		}
	}
	map<int,int> mp;
	int maxx=0,id=0;
	sort(a+1,a+1+n,greater<int>());
	for(int i=1;i<=n;i++){
		if(mp[g[a[i]]]) mp[a[i]]=mp[g[a[i]]]+1;
		else mp[a[i]]=1;
		if(mp[a[i]]>maxx){
			maxx=mp[a[i]];
			id=a[i];
		}
	}
	vector<int> ans;
	ans.push_back(id);
	while(mp[g[id]]){
		id=g[id];
		ans.push_back(id);
	}
	cout<<ans.size()<<endl;
	for(auto i:ans){
		cout<<i<<" ";
	}
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t=1;
	//cin>>t;
	while(t--) solve();
} 
from itertools import permutations
n=int(input())
a=[0]*(n+1)
g={}
for i in range(1,n+1):
    a[i]=int(input())
    bit=[0]*32
    for j in range(32):
        if a[i]>>j&1: bit[31-j]=1
    for bit_permutation in permutations(bit):
        for j in range(32):
            if bit_permutation[31-j]: g[a[i]]|=1<<j
mp={}
maxx=0
id=0
a.sort(reverse=True)
for i in range(1,n+1):
    if g[a[i]] in mp: mp[a[i]]=mp[g[a[i]]]+1
    else: mp[a[i]]=1
    if mp[a[i]]>maxx:
        maxx=mp[a[i]]
        id=a[i]
ans=[id]
while g.get(id):
    id=g[id]
    ans.append(id)
print(len(ans))
print(*ans)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值