Atcoder Beginner Contest 242(A-F)

在 Print 之前

又是一篇 A t c o d e r Atcoder Atcoder 的题解,星期二(3.4)打了一场 v p vp vp,赛时做出来了5道,第六道赛时觉得太抽象没写出来

A - T-shirt

题目

只需判断 X ≤ A X \le A XA A + 1 ≤ X ≤ B A+1 \le X \le B A+1XB,以及 B + 1 ≤ X B+1 \le X B+1X,这几种情况,输出即可 (没啥好说的)

A - Code

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=1e3+5;
ll a,b,c,x;
double ans;
int main() {
    cin>>a>>b>>c>>x;
    if(x<=a) ans=1;
    else if(x>a&&x<=b) {
        ans=c;
        ans/=(b-a);
    }
    printf("%.12lf",ans);
    return 0;
}

B - Minimize Ordering

题目

更简单,只需 c i n cin cin,然后 s o r t sort sort,最后 c o u t cout cout

B - Code

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=2e5+5;
string s;
int main() {
    cin>>s;
    sort(s.begin(),s.end());
    cout<<s;
    return 0;
}

C - 1111gal password

题目

有点像数位dp

我们只需要思考上一位比它大一或比它小一的数,把情况加起来即可,即:
n u m i , j = n u m i − 1 , j + n u m i − 1 , j − 1 + n u m i − 1 , j + 1 ; num_{i,j}=num_{i-1,j}+num_{i-1,j-1}+num_{i-1,j+1}; numi,j=numi1,j+numi1,j1+numi1,j+1;

我们又会思考,为什么不特判 1 1 1 9 9 9 呢,不难想到, n u m i , 0 num_{i,0} numi,0 n u m i , 10 num_{i,10} numi,10 都为 0 0 0,所以不会影响结果。

C - Code

#include <bits/stdc++.h>
#define ll long long
#define mod 998244353
using namespace std;
const ll N=1e6+5;
ll n,num[N][15],ans;
int main() {
    cin>>n;
    for(ll i=1;i<=9;i++) {
        num[1][i]=1;
    }
    for(ll i=2;i<=n;i++) {
        for(ll j=1;j<=9;j++) {
            num[i][j]=num[i-1][j]+num[i-1][j-1]+num[i-1][j+1];
            num[i][j]%=mod;
        }
    }
    for(ll i=1;i<=9;i++) {
        ans+=num[n][i];
        ans%=mod;
    }
    cout<<ans;
    return 0;
}

D - ABC Transform

题目

我们不难发现,它每次分裂出两个节点,这是啥,二叉树啊,请看图:

所以我们只需用一个变量统计一下单复数,左根加 1 1 1 右根加 2 2 2,即:
s u m + = { 1 if   k ≡ 1 ( m o d 2 ) 2 if   k ≡ 0 ( m o d 2 ) sum += \begin{cases} 1 & \text{if } \text{ } k \equiv 1 \pmod 2\\ 2 & \text{if } \text{ } k \equiv 0 \pmod 2 \end{cases} sum+={12if  k1(mod2)if  k0(mod2)

注意,如果 60 ≤ t 60 \le t 60t 那么数肯定大于 1 0 18 10^{18} 1018

D - Code

#include <bits/stdc++.h>
#define ll long long
#define mod 998244353
using namespace std;
const ll N=1e6+5;
ll q;
string s;
char ans;
int main() {
    cin>>s>>q;
    while(q--) {
        ll k,t;
        cin>>t>>k;
        ll sum=0;
        while(1) {
            if(!t||k==1) break;
            if(k%2==1) sum++;
            else sum+=2;
            k=(k+1)/2;
            t--;
        }
        if(t) {
            ans=(s[0]-'A'+sum+t)%3+'A';
        }
        else {
            ans=(s[k-1]-'A'+sum)%3+'A';
        }
        cout<<ans<<endl;
    }
    return 0;
}

E - (∀x∀)

题目

这题我居然给自己挖了两个坑,还都跳下去了

我们考虑回文字符串是如何构成的,是由前面大约 n ÷ 2 n \div 2 n÷2 个字符翻转拼接而成。

如果我们考虑前面这些字符串,字典序已经比原串的字典序小了,那么这个回文串的字典序一定比原串小。

问题转化为,前 n ÷ 2 n \div 2 n÷2 个字符构成的字符串,有多少个字符串的字典序比它小。

我们还需考虑前 n ÷ 2 n \div 2 n÷2 如果和原字符串字典序相同,还可能构成字符串,所以我们需要把这个字符串构造出来,和原串比较字典序即可。

时间复杂度 O ( T n ) O(Tn) O(Tn)

E - Code

#include <bits/stdc++.h>
#define ll long long
#define mod 998244353
using namespace std;
const ll N=1e6+5;
ll T,n,ans,f;
string s,str1,str2;
int main() {
    cin>>T;
    while(T--) {
        ans=0,f=1;
        cin>>n>>s;
        ll num=(n+1)/2;
        for(ll i=0;i<num;i++) {
            ll cnt=s[i]-'A';
            ans*=26;
            ans+=cnt;
            ans%=mod;
        }
        str1="";
        str2="";
        for(ll i=num-1;i>=0;i--) {
            str1+=s[i];
        }
        if(n%2==0) num++;
        for(ll i=num-1;i<n;i++) {
            str2+=s[i];
        }
        if(str1>str2) f=0;
        cout<<(ans+f)%mod<<endl;
    }
    return 0;
}

F - Black and White Rooks

题目

题解参照这篇

思路大致相同,但需注意如何 m o d mod mod

F - Code

#include <bits/stdc++.h>
#define ll long long
#define mod 998244353
using namespace std;
const ll N=5e1+5;
ll n,m,b,w,ans,f[N][N],g[N][N],c[N*N][N*N];
int main() {
	cin>>n>>m>>b>>w;
	c[0][0]=1;
	for(ll i=1;i<=2500;i++) {
		c[i][0]=1;
        c[i][i]=1;
		for(ll j=1;j<=2500;j++) {
			c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
		}
	}
	for(ll i=1;i<=n;i++) {
		for(ll j=1;j<=m;j++) {
			f[i][j]=c[i*j][b];
			for(ll l=1;l<=i;l++) {
				for(ll r=1;r<=j;r++) {
					if(l==i&&r==j) continue;
                    ll cnt=f[l][r];
                    cnt*=c[i][l];
                    cnt%=mod;
                    cnt*=c[j][r];
                    cnt%=mod;
					f[i][j]=(f[i][j]-(cnt+mod)%mod+mod)%mod;
				}
            }
		}
	}
	for(ll i=1;i<=n;i++) {
		for(ll j=1;j<=m;j++) {
			g[i][j]=c[i*j][w];
			for(ll l=1;l<=i;l++) {
				for(ll r=1;r<=j;r++) {
					if(l==i&&r==j) continue;
                    ll cnt=g[l][r];
                    cnt*=c[i][l];
                    cnt%=mod;
                    cnt*=c[j][r];
                    cnt%=mod;
					g[i][j]=(g[i][j]-(cnt+mod)%mod+mod)%mod;
				}
            }
		}
	}
	for(ll i=1;i<=n;i++) {
		for(ll j=1;j<=n-i;j++) {
			for(ll l=1;l<=m;l++) {
				for(ll r=1;r<=m-l;r++) {
                    ll cnt=c[n][i];
                    cnt*=c[n-i][j];
                    cnt%=mod;
                    cnt*=c[m][l];
                    cnt%=mod;
                    cnt*=c[m-l][r];
                    cnt%=mod;
                    cnt*=f[i][l];
                    cnt%=mod;
                    cnt*=g[j][r];
                    cnt%=mod;
					ans+=cnt;
                    ans%=mod;
				}
			}
		}
	}
	cout<<ans;
	return 0;
}
### AtCoder ABC284F 解法探讨 对于AtCoder Beginner Contest (ABC) 284中的题目F,该问题通常涉及较为复杂的算法设计和数据结构应用。虽然具体题面未在此提供,但基于以往的经验以及竞赛编程的特点,可以推测这类高难度题目往往考察动态规划、图论或是高级的数据处理技巧。 针对此类问题的解决方案一般遵循以下思路: 1. **理解题意** 对于任何算法竞赛题目而言,清晰的理解问题是解决问题的第一步。仔细阅读题目描述,确保完全明白输入输出的要求及其约束条件[^1]。 2. **分析样例** 利用给定的例子来验证自己的想法是否正确,并尝试找出规律或模式。这有助于构建初步的解题框架并发现潜在陷阱。 3. **选择合适的方法** 根据问题特性挑选最适宜的技术手段。例如,在本案例中可能涉及到树形DP、贪心策略或者其他高效能算法的设计与实现。 4. **优化性能** 考虑到时间复杂度和空间复杂度的要求,对初始方案进行必要的改进以满足严格的资源限制。此过程或许会引入更精妙的数据结构支持快速查询更新操作。 5. **编写代码** 使用所选定的语言(如C++、Python等),按照上述逻辑严谨地编码实现。注意边界情况处理及异常检测机制的应用。 6. **测试调试** 编写完成后利用多种类型的测试集进行全面检验,直至程序能够稳定运行并通过官方评测系统验收为止。 下面给出一段简化版伪代码作为示范: ```cpp // 假设这是一个关于某种特定场景下的求解函数 void solve() { // 初始化变量... // 主要计算流程... // 输出最终结果... } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值