Codeforces 1016

A - Ideal Generator

题目:

非常简单,从样例都可以看出只要 k k k 是奇数就是,反之不是。

因为当 k k k 为奇数时,这个回文数中间有一个单独的数,这个数可以是任意一个数,所以很容易满足回文,但如果是偶数,就要严格满足一 一对应关系,所以明显有数不行。

代码过分简单,读者自己写。(lazy~)

B - Expensive Number

题目:

很明显,我们首先要找出最小代价是多少。很明显是 1 1 1,也就是当这个数本身与各个数位上的数相加后的和相等时成立。

那在什么时候这个条件会成立?答案是只有一位数字时。这个也很明显,在此不多做讨论。

那么这道题改一下就成了这样:

给你一个数,让你删掉一些数位上的数使得这个数最终是一个一位数,求删掉的最少数量。

因为题目中允许有前导 0 0 0,所以对于一个数位 i i i,它前面只需要删掉不是 0 0 0 的数,而后面则需要全部删掉。

现在我们要让这个删掉的数位数量最少,那我们就要确定一个 i i i 使得它最小。那我们又该在什么时候开始删呢?

我们找删除数位这个过程中最特殊的情况:前面只需要删掉不是 0 0 0 的数。那么我们让尽可能多的 0 0 0 在前面不就行了?反过来说,我们要找的这个 i i i 是从后往前第一个不是 0 0 0 的那一位。

然后就 A C \color{green}{AC} AC 了!

代码:

#include<bits/stdc++.h>
#define ll long long
#define inf 2e18
const ll mod=1e9+7;
namespace io {
	using namespace std;
	inline ll read() {
		char n=getchar();
		ll num=0,flag=1;
		while(n<'0'||n>'9') {
			if(n=='-') {
				flag=-1;
			}
			n=getchar();
		}
		while(n>='0'&&n<='9') {
			num=num*10+n-'0';
			n=getchar();
		}
		return num*flag;
	}
	inline void print(ll x) {
		if(x<0) {
			putchar('-');
			print(-x);
			return;
		}
		if(x==0) {
			return;
		}
		print(x/10);
		putchar((char)(x%10+'0'));
	}
}
using namespace io;
const ll N=1e2+5;
ll T,n[N],cnt,ans;
double k=inf;
string s;
map<char,bool> mp;
bool f;
void solve() {
	cin>>s;
	if(s.size()==1) {
		cout<<0<<endl;
		return ;
	}
	cnt=0;
	f=0;
	for(ll i=s.size()-1;i>=0;i--) {
		if(s[i]=='0') {
			if(!f) cnt++;
		}
		else {
			f=1;
			cnt++;
		}
	}
	cout<<cnt-1<<endl;
}
int main(){
	T=read();
	while(T--) {
		solve();
	}
	return 0;
}

C - Simple Repetition

题目:

这道题也是毁常的简单啊。

对于 x x x k k k,我们可以按照它们的特殊性把它们分成三类: { x ≠ 1 , k = 1 x = 1 , k ≠ 1 x ≠ 1 , k ≠ 1 \begin{cases}x\not=1,k=1\\x=1,k\not=1\\x\not=1,k\not=1\end{cases} x=1,k=1x=1,k=1x=1,k=1

1. x ≠ 1 , k = 1 x\not=1,k=1 x=1,k=1

这种时候最简单,只需要判断 x x x 是不是质数就行了。


2. x = 1 , k ≠ 1 x=1,k\not=1 x=1,k=1

这种情况稍微有点复杂,我们可以通过列举来看看哪些是质数、哪些是合数:

其实通过找规律我们也能很明显的看出:当 k = 2 k=2 k=2 时是质数,其余情况都不是,具体证明我也不会,会证明的读者麻烦在评论区展示一下。


3. x ≠ 1 , k ≠ 1 x\not=1,k\not=1 x=1,k=1

这种情况也很简单,因为由 k k k x x x 所组成的数必然能拆成 x × 1 0000 … 1 ⏟ x 的位数 … ⏟ k − 1 个 x\times1\underbrace{\underbrace{0000\dots1}_{x\text{的位数}}\dots}_{k-1\text{个}} x×1k1 x的位数 00001,因此它必然是合数。

代码:

#include<bits/stdc++.h>
#define ll long long
#define inf 2e18
const ll mod=1e9+7;
namespace io {
	using namespace std;
	inline ll read() {
		char n=getchar();
		ll num=0,flag=1;
		while(n<'0'||n>'9') {
			if(n=='-') {
				flag=-1;
			}
			n=getchar();
		}
		while(n>='0'&&n<='9') {
			num=num*10+n-'0';
			n=getchar();
		}
		return num*flag;
	}
	inline void print(ll x) {
		if(x<0) {
			putchar('-');
			print(-x);
			return;
		}
		if(x==0) {
			return;
		}
		print(x/10);
		putchar((char)(x%10+'0'));
	}
}
using namespace io;
const ll N=1e2+5;
ll T,k,n;
string s;
ll sspd(ll x) {
    if(x==1) return false;
    for(ll i=2;i<=x/i;i++) {
        if(x%i==0) return false;
    }
	return true;
}
void solve() {  
    cin>>n;
    s=to_string(n);
    cin>>k;
    if(n==1) {
        if(k==2) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    else if(k>1) {
        cout<<"NO"<<endl;
    }
	else if(k==1) {
        if(sspd(n)) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    } 
} 
int main(){
	T=read();
	while(T--) {
		solve();
	}
	return 0;
}

D - Skibidi Table

题目:

一道很简单的分治,这里我就不过多赘述了,大家自己推一下函数,也没什么难的,反正代码在下面:

#include <bits/stdc++.h>
#define ll long long
namespace io {
	using namespace std;
	inline ll read() {
		char n=getchar();
		ll num=0,flag=1;
		while(n<'0'||n>'9') {
			if(n=='-') {
				flag=-1;
			}
			n=getchar();
		}
		while(n>='0'&&n<='9') {
			num=num*10+n-'0';
			n=getchar();
		}
		return num*flag;
	}
	inline void print(ll x) {
		if(x<0) {
			putchar('-');
			print(-x);
			return;
		}
		if(x==0) {
			return;
		}
		print(x/10);
		putchar((char)(x%10+'0'));
	}
}
using namespace io;
ll T,n,q;
string op;
struct node {
	ll x,y;
};
ll dfs1(ll id,ll l,ll r,ll x,ll y) {
    if(l==x&&r==y) {
        return 1;
	}
    ll dt=1<<(id-1);
	ll dd=dt*dt;
    if(x>=l+dt&&y>=r+dt) {
        return dd+dfs1(id-1,l+dt,r+dt,x,y);
	}
    if(x>=l+dt) {
        return (dd<<1)+dfs1(id-1,l+dt,r,x,y);
	}
    if(y>=r+dt) {
        return dd*3+dfs1(id-1,l,r+dt,x,y);
	}
    return dfs1(id-1,l,r,x,y);
}
node dfs2(ll id,ll l,ll r,ll d) {
    if(d==1) {
        return (node){l,r};
	}
    ll dt=1<<(id-1);
	ll dd=dt*dt;
    if(d>3*dd) {
        return dfs2(id-1,l,r+dt,d-3*dd);
	}
    if(d>(dd<<1)) {
        return dfs2(id-1,l+dt,r,d-(dd<<1));
	}
    if(d>dd) {
        return dfs2(id-1,l+dt,r+dt,d-dd);
	}
    return dfs2(id-1,l,r,d);
}
void solve() {
    n=read();
    q=read();
    while(q--) {
		ll x,y;
        cin>>op;
        x=read();
        if(op[0]=='-') {
            y=read();
            ll ans=dfs1(n,1,1,x,y);
            if(ans==0) putchar('0');
            print(ans);
        }
		else {
            node ans=dfs2(n,1,1,x);
            if(ans.x==0) putchar('0');
            print(ans.x);
            putchar(' ');
            if(ans.y==0) putchar('0');
            print(ans.y);
        }
        putchar('\n');
    }
}
int main() {
    T=read();
    while(T--) {
        solve();
	}
    return 0;
}

E - Min Max MEX

题目:

首先我们明确一点: MEX ⁡ \operatorname{MEX} MEX 的定义。

MEX ⁡ \operatorname{MEX} MEX 指一串自然数里面没出现的最小非负整数。而题目然我们求最大的 MEX ⁡ \operatorname{MEX} MEX,这听上去是不是很耳熟?对了,最小的最大

一眼算法:二分

然后重点就在于判断函数怎么写。

既然直接硬钢不好做,我们反着来。我们不是二分出了一个当前的 MEX ⁡ \operatorname{MEX} MEX 吗,为什么我们不用当前二分出来的这个 MEX ⁡ \operatorname{MEX} MEX 来反过来算要割成几份呢?然后再验证一下个数是不是大于等于 k k k 就对了。

代码:

#include<bits/stdc++.h>
#define ll long long
#define inf 2e18
const ll mod=1e9+7;
namespace io {
	using namespace std;
	inline ll read() {
		char n=getchar();
		ll num=0,flag=1;
		while(n<'0'||n>'9') {
			if(n=='-') {
				flag=-1;
			}
			n=getchar();
		}
		while(n>='0'&&n<='9') {
			num=num*10+n-'0';
			n=getchar();
		}
		return num*flag;
	}
	inline void print(ll x) {
		if(x<0) {
			putchar('-');
			print(-x);
			return;
		}
		if(x==0) {
			return;
		}
		print(x/10);
		putchar((char)(x%10+'0'));
	}
}
using namespace io;
const ll N=2e5+5;
ll T,n,k,a[N];
bool ck(ll x) {
	vector<ll> mp(x+5,0);
	ll cnt=0,pos=0;
	for(ll i=1;i<=n;i++) {
		if(a[i]<x&&!mp[a[i]]) {
			mp[a[i]]=1;
			pos++;
		}
		if(pos>=x) {
			cnt++;
			pos=0;
			for(ll j=0;j<=x;j++) {
				mp[j]=0;
			}
		}
	}
	if(cnt>=k) {
		return true;
	}
	return false;
}
void solve() {  
    n=read();
	k=read();
	for(ll i=1;i<=n;i++) {
		a[i]=read();
	}
	ll l=0,r=n,ans=0;
	while(l<r) {
		ll mid=(l+r+1)>>1;
		if(ck(mid)) {
			l=mid;
			ans=mid;
		}
		else {
			r=mid-1;
		}
	}
	if(!ans) putchar('0');
	else print(ans);
	cout<<endl;
}
int main() {
	T=read();
	while(T--) {
		solve();
	}
	return 0;
}

F - Hackers and Neural Networks

题目:

说句实话:我一开始看到这道题连样例都没看懂,后面经过大佬指点后才明白了这道题的真正含义,实在是有点奇怪,让我来给你“翻译”一下:

最初,黑客们有一个长度为 n n n 的序列 c c c,而 c c c 初始为空,在第一次操作中,它需要选择一个 b i b_i bi 使它自己等于 b i b_i bi,然后再按照上面的规则进行替换,问最少操作次数。

(其实我也不知道题目怎么叙述着叙述着就成这样了……)

那这下意思就很简单了啊,用个贪心找到与 a a a 共同点最多的,记录下来,然后初始化就等于这个字符串,最后再按照上面的操作一顿操作就行了。

那如何判断 − 1 -1 1 的情况?也很简单,你想:如果你把所有的字符串都用完了还是不能凑出 a a a,那不就凉了吗?反之就没事,所以加个标记数组就完事。

代码:

#include<bits/stdc++.h>
#define ll long long
namespace io {
	using namespace std;
	inline ll read() {
		char n=getchar();
		ll num=0,flag=1;
		while(n<'0'||n>'9') {
			if(n=='-') {
				flag=-1;
			}
			n=getchar();
		}
		while(n>='0'&&n<='9') {
			num=num*10+n-'0';
			n=getchar();
		}
		return num*flag;
	}
	inline void print(ll x) {
		if(x<0) {
			putchar('-');
			print(-x);
			return;
		}
		if(x==0) {
			return;
		}
		print(x/10);
		putchar((char)(x%10+'0'));
	}
}
using namespace io;
const ll N=5e2+5;
ll n,m,k,t,cnt,num[N],ans;
bool f;
string a[N],b[N][N];
int main() {
	cin>>t;
	while(t--) {
        memset(num,0,sizeof(num));
		cin>>n>>m;
		f=0,ans=0,cnt=0;
		for(ll i=1;i<=n;i++) {
            cin>>a[i];
        }
		for(ll i=1;i<=m;i++) {
            for(ll j=1;j<=n;j++) {
                cin>>b[i][j];
            }
        }
		for(ll i=1;i<=m;i++) {
			for(ll j=1;j<=n;j++) {
				if(b[i][j]==a[j]) {
					cnt++;
					num[j]=1;
				}
			}
			ans=max(ans,cnt);
			cnt=0;
		}
		for(ll i=1;i<=n;i++) {
			if(num[i]==0) {
                f=1;
            }
		}
		if(!f) {
            cout<<n+2*(n-ans);
        } 
        else {
            cout<<"-1";
        }
        cout<<endl;
	}
	return 0;
}

G - Shorten the Array

题目:

(瞅我干啥,我不会。)

按照我们机房里另一位大佬的写法,这题应该是一个 Trie 树(字典树),但我不会……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值