arc113游玩记

arc 113 游玩记

\(~~~~\) 算是赛后开了一个虚拟赛吧(显然没有 Atcoder 在线赛的感觉以及在意不能随意交代码)

A. A*B*C

题意

\(~~~~\) 求使得 \(a\times b\times c\leq k\) 的三元组 \((a,b,c)\) 的个数,\(1\leq k\leq 5\times 10^5\)

题解

\(~~~~\) 怎么简单怎么来,直接枚举 \(a,b\)\(O(1)\) 计算 \(c\) 的个数,时间复杂度 \(\mathcal{O(k\times \ln k)}\)

\(~~~~\) 谁还打整除分块啊。

代码

#include <cstdio>
#include <algorithm>
#define ll long long
using namespace std;
int main() {
	int K;
	ll Ans=0;
	scanf("%d",&K);
	for(int i=1;i<=K;i++)
	{
		for(int j=1;j<=K;j++)
		{
			if(i*j>K) break;
			Ans+=(K/(i*j));
		}
	}
	printf("%lld",Ans);
	return 0;
}

B.\(A^{B^C}\)

题意

\(~~~~\) 给定三个数 \(a,b,c\) ,求出 \(a^{b^c}\) 的个位上的数。

\(~~~~\) 不难(指赛时WA了两发)发现所有一位数的次幂在 \(4\) 的时候都会循环,因此计算 \(\large a^{b^c \bmod 4}\bmod 10\) 即可。

代码

#include <cstdio>
#include <algorithm>
#define ll long long
using namespace std;
ll qpow(ll a,ll b,ll MOD)
{
	ll ret=1;
	while(b)
	{
		if(b&1) ret=ret*a%MOD;
		b>>=1;a=a*a%MOD; 
	}
	return ret;
}
int main() {
	ll a,b,c;
	scanf("%lld %lld %lld",&a,&b,&c);
	a%=10;
    //略写得复杂一些
	if(a==0||a==1||a==5||a==6) printf("%lld",a);
	if(a==2||a==3||a==7||a==8) printf("%lld",qpow(a,qpow(b,c,4)+4,10));
	if(a==4||a==9) printf("%lld",qpow(a,(qpow(b,c,2))+2,10));
	return 0;
}

C.String Invasion

题意

693a75c0fc304.png

\(~~~~\) 显然贪心倒着来,发现一个东西如果能开始替换的话直接把后面换完即可,以此类推。

\(~~~~\) 实现的时候注意到与上一个可换字符之间重复的字符要减去以及与上一个是否一致。

\(~~~~\) 还有开 long long

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
char s[200005];
int buc[200005][27];
int main() {
	scanf("%s",s+1);
	int len=strlen(s+1);
	int Last=0,pos=len;
	ll Ans=0;
	for(int i=len;i>=1;i--)
	{
		buc[i][s[i]-'a']++;
		for(int j=0;j<26;j++) buc[i][j]+=buc[i+1][j];
	}
	for(int i=len-1;i>=1;i--)
	{
		if(s[i]==s[i+1]&&s[i+1]!=s[i+2])
		{
			if(Last==s[i]) Ans+=(pos-1-(i+2)+1);
			else Ans+=len-(i+2)+1;
			if(i!=len-1) Ans-=buc[i+2][s[i]-'a']-buc[pos][s[i]-'a'];
			pos=i;Last=s[i];
		}
	}
	printf("%lld",Ans);
	return 0;
}
/*
aaabbbccc
*/

D.Sky Reflector

题意

\(~~~~\) 给定 \(N,M,K\),对于一个 \(N\)\(M\) 列的正整数矩阵,\(A_i\) 是第 \(i\) 行的最小值,\(B_j\) 是第 \(j\) 列的最大值,网格中每个数的大小不超过 \(K\),求所有可能被构造出来的 \((A,B)\)的个数(答案对 \(998244353\) 取模)

题解

\(~~~~\) 大胆猜测 \(\max\{A\} \leq \min \{B\}\) 是合法的即可。

\(~~~~\) 我有一个绝妙的证明,但我没时间写了。

\(~~~~\) 同时注意特判 \(n=1\)\(m=1\) 时答案为 \(k^{nm}\)

代码

#include <cstdio>
#include <algorithm>
#define ll long long
const int MOD=998244353;
ll qpow(ll a,ll b)
{
	ll ret=1;
	while(b)
	{
		if(b&1) ret=ret*a%MOD;
		b>>=1;a=a*a%MOD; 
	}
	return ret;
}
int main() {
	int n,m,k;
	ll Ans=0;
	scanf("%d %d %d",&n,&m,&k);
	if(n==1)
	{
		printf("%lld",qpow(k,m));
		return 0;
	}
	if(m==1)
	{
		printf("%lld",qpow(k,n));
		return 0;
	}
	for(int i=1;i<=k;i++)
	{
		Ans+=(((qpow(i,n)-qpow(i-1,n))%MOD+MOD)%MOD*qpow(k-i+1,m))%MOD;
		Ans=Ans%MOD; 
	}
	printf("%lld",Ans);
	return 0;
}

E.Rvom and Rsrev

Click Here

F.Social Distance

积分,不会,告辞

posted @ 2021-04-15 22:21  Azazеl  阅读(210)  评论(0)    收藏  举报