【AtCoder】AtCoder Beginner Contest 110题解

AtCoder Beginner Contest 110题解

A - Maximize the Formula

◇题目传送门◆

题目大意

给定三个数字 A , B , C A,B,C A,B,C,要求使用这三个数字组成一个两位数及一个一位数,使得他们的和最大

思路

似乎没有什么可以讲的,直接给出代码吧。

代码

#include<cstdio>
#include<algorithm>
using namespace std;

int main() {
	#ifdef LOACL
	freopen("in.txt","r",stdin);
	freopen("out.txt","w",stdout);
	#endif
	int a[3];
	scanf("%d %d %d",&a[0],&a[1],&a[2]);
	sort(a,a+3);
	printf("%d\n",a[2]*10+a[1]+a[0]);
	return 0;
}

B - 1 Dimensional World’s Tale

◇题目传送门◆

题目大意

给定两个数 N , M N,M N,M和数轴上的两个点 X , Y X,Y X,Y N N N个点 x 1 , x 2 , x 3 , … , x N x_1,x_2,x_3,\ldots,x_N x1,x2,x3,,xN M M M个点 y 1 , y 2 , y 3 , … , y M y_1,y_2,y_3,\ldots,y_M y1,y2,y3,,yM,要求找出一个点 Z Z Z,使得它满足以下条件:

  • X &lt; Z ≤ Y X&lt;Z\le Y X<ZY
  • x 1 , x 2 , x 3 , … , x N &lt; Z x_1,x_2,x_3,\ldots,x_N&lt;Z x1,x2,x3,,xN<Z
  • y 1 , y 2 , y 3 , … , y M ≥ Z y_1,y_2,y_3,\ldots,y_M\ge Z y1,y2,y3,,yMZ

思路

我们记 x 0 = X , y 0 = Y x_0=X,y_0=Y x0=X,y0=Y,仔细分析题目可以发现,当存在 max ⁡ { x 0 , x 1 , x 2 , … , x N } &lt; min ⁡ { y 0 , y 1 , y 2 … , y M } \max\{x_0,x_1,x_2,\ldots,x_N\}&lt;\min\{y_0,y_1,y_2\ldots,y_M\} max{x0,x1,x2,,xN}<min{y0,y1,y2,yM}时,就会有 Z Z Z存在。

所以直接给出代码:

代码

#include<cstdio>
#include<algorithm>
using namespace std;

const int Maxn=100;
int N,M,X,Y;
int A[Maxn+5],B[Maxn+5];

int main() {
	#ifdef LOACL
	freopen("in.txt","r",stdin);
	freopen("out.txt","w",stdout);
	#endif
	scanf("%d %d %d %d",&N,&M,&A[0],&B[0]);
	for(int i=1;i<=N;i++)
		scanf("%d",&A[i]);
	for(int i=1;i<=M;i++)
		scanf("%d",&B[i]);
	int maxa=*max_element(A,A+N+1);
	int minb=*min_element(B,B+M+1);
	if(maxa<minb)
		puts("No War");
	else puts("War");
	return 0;
}

C - String Transformation

◇题目传送门◆

题目大意

给定两个串 S , T S,T S,T,保证两串长度相等。要求使用如下操作,使得 S , T S,T S,T相同:

操作:从26个字母中选择两个字母 c 1 , c 2 c_1,c_2 c1,c2,在 S S S中,将所有的 c 1 c_1 c1替换为 c 2 c_2 c2,所有的 c 2 c_2 c2替换为 c 1 c_1 c1

思路

不难发现在串 S S S中,每个字母和串 T T T中的每个字母是有一一对应的关系。所以我们考虑在串 S S S中是否满足这个对应关系,在串 T T T中是否满足对应关系。想到这个即可过掉此题。

代码

#include<set>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int Maxn=2*1e5;

char s[Maxn+5],t[Maxn+5];
int c[256+5];

int main() {
	#ifdef LOACL
	freopen("in.txt","r",stdin);
	freopen("out.txt","w",stdout);
	#endif
	scanf("%s %s",s,t);
	int len=strlen(s);
	memset(c,-1,sizeof c);
	set<char> cnt;
	for(int i=0;i<len;i++)
		cnt.insert(s[i]);
	for(int i=0;i<len;i++) {
		if(c[t[i]]!=-1&&c[t[i]]!=s[i]) {
			if(t[i]==s[i]&&cnt.size()<26)
				continue;
			puts("No");
			return 0;
		}
		c[t[i]]=s[i];
	}
	memset(c,-1,sizeof c);
	for(int i=0;i<len;i++) {
		if(c[s[i]]!=-1&&c[s[i]]!=t[i]) {
			if(t[i]==s[i]&&cnt.size()<26)
				continue;
			puts("No");
			return 0;
		}
		c[s[i]]=t[i];
	}
	puts("Yes");
	return 0;
}

D - Factorization

◇题目传送门◆

题目大意

给定两个数 N , M N,M N,M,要求找出 N N N个数,使得这 N N N个数的乘积等于 M M M。输出方案数模 1 0 9 + 7 10^9+7 109+7

思路

仔细分析可发现,这 N N N个数要么是 1 1 1,要么就是 N N N的质因数的乘积。

很自然的就扯到了唯一分解和组合数学上去。

M = p 1 a 1 p 2 a 2 ⋯ p m a m M=p_1^{a_1}p_2^{a_2}\cdots p_m^{a_m} M=p1a1p2a2pmam,其中 p 1 , p 2 , … , p m p_1,p_2,\ldots,p_m p1,p2,,pm为质数。

当我们将 a i a_i ai个质数 p i p_i pi(其中 1 ≤ i ≤ m 1\le i\le m 1im)加入到 N N N个数中,就相当于将 N + a i − 1 N+a_i-1 N+ai1个数分成 N − 1 N-1 N1块的组合数。

所以我们就可以得到:此时的方案数为 C ( N + a i − 1 , N − 1 ) C(N+a_i-1,N-1) C(N+ai1,N1)。而由于在两个方案之间,有一个数不同即被视为不同,所以,我们只需要将所有的方案数乘上即可。

即方案数为 ∏ i = 1 m C ( N + a i − 1 , N − 1 ) \prod_{i=1}^{m}C(N+a_i-1,N-1) i=1mC(N+ai1,N1)

注意此时若 M ≠ 1 M\ne1 M̸=1时,答案是还需乘上 N N N的。(请读者自己思考)

特别注意:由于这道题要求取模,而组合数计算需要除法,所以我们必须使用逆元!不知道逆元的读者请点这里

接下来分析时间复杂度:

预处理阶乘和逆元需要 O ( N log ⁡ 2 M o d ) O(N\log_2Mod) O(Nlog2Mod)

唯一分解所需要的时间为 O ( M ) O(\sqrt{M}) O(M )

计算答案需要 O ( 1 ) O(1) O(1)

又由于 N N N远小于 M M M,所以,总时间复杂度为 O ( M ) O(\sqrt{M}) O(M )

代码

#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;

typedef long long ll;
const int Mod=1e9+7;
const int Maxn=1.5*1e5;

int N,M;

ll PowMod(ll a,int b) {
    ll ret=1;
    while(b) {
        if(b&1)ret=ret*a%Mod;
        a=a*a%Mod;
        b>>=1;
    }
    return ret;
}

ll f[Maxn+5];
ll inv[Maxn+5];

void Prepare() {
	f[0]=1;
	for(int i=1;i<=Maxn;i++)
	    f[i]=f[i-1]*i%Mod;
	inv[0]=1;
	inv[Maxn]=PowMod(f[Maxn],Mod-2);
	for(int i=Maxn-1;i>0;i--)
	    inv[i]=inv[i+1]*(i+1)%Mod;
}

ll F(int a,int b) {
    return f[a+b-1]*inv[a-1]%Mod*inv[b]%Mod;
}//C(a+b-1,a-1)

int main() {
	#ifdef LOACL
	freopen("in.txt","r",stdin);
	freopen("out.txt","w",stdout);
	#endif
	scanf("%d %d",&N,&M);
	Prepare();
	int lim=sqrt(M);
	ll ans=1;
	for(int i=2;i<=lim;i++)
		if(M%i==0) {
			int cnt=0;
			while(M%i==0)
				M/=i,cnt++;
			ans=ans*F(N,cnt)%Mod;
		}
	if(M!=1)ans=ans*N%Mod;
	printf("%lld",ans);
	return 0;
}

最后给出我的排名:

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值