专栏文章
题解:AT_abc304_f [ABC304F] Shift Table
AT_abc304_f题解参与者 3已保存评论 6
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 6 条
- 当前快照
- 1 份
- 快照标识符
- @miqg5gsn
- 此快照首次捕获于
- 2025/12/04 04:15 3 个月前
- 此快照最后确认于
- 2025/12/04 04:15 3 个月前
题目传送门
题目大意
高桥和青木将在接下来的 天兼职工作。
高桥的轮班时间表由字符串 给出,其中,如果他在 天工作,则 的第 个字符为
#,如果他在 天缺勤,则为 .。基于此,Aoki 创建了他的轮班时间表,如下所示。
- 首先,取 的正除数 ,该除数不等于 。
- 接下来,确定前 天的出勤率。
- 最后,按照此顺序,对于 ,确定第 天的出勤率,使其与第 天的出勤率相匹配。
请注意,不同的 值可能会导致相同的最终轮班安排。
找出青木可能的轮班安排数量,使得 高桥和青木中至少有一人在 天的每一天工作,模数为 。
思路
很明显如果高桥第 天没工作,那么青木第 天就只有一种情况(必须工作);而如果高桥第 天工作了,那么青木第 天就有两种情况(工作或者不工作),所以我们只需要遍历找 ,如果有高桥没工作的,答案乘以 。
但是这样我们又会发现一个问题:当遍历的循环节为倍数关系时(如:)那么就会有重复计算部分,这种我们就需要用一个数组记录重复部分,在必要时候减去重复部分,然后就 OK 啦!
代码
CPP#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=200005,m=998244353;
ll n,ans,v[N],c,f;/*c用来存储计算过程中可能的组合数 f用来判断某天是否需要工作 通过数组v[i]来防止重复计算*/
string s;
int main(){
cin>>n>>s,s=" "+s;/*使s下标从1开始*/
for(int i=1;i<n;i++){/*遍历找m*/
if(n%i==0){/*找到符合条件m*/
c=1;
for(int j=1;j<=i;j++){/*以i为循环节遍历每天是否需要值班*/
f=0;
for(int k=j;k<=n;k+=i)if(s[k]=='.'){f=1;break;}/*如果高桥这天没值班青木这天必须值班*/
if(f==0)c=(c*2)%m;/*方案数X2(01值班或不值)*/
}
ans=(ans+c-v[i]+m)%m;/*计算答案,-v[i]去重 +m防止ans<0*/
for(int j=i+i;j<=n;j+=i)v[j]=(v[j]+c-v[i]+m)%m;/*去重数组i的倍数值刷新 +m同上*/
}
}
cout<<ans;
return 0;
}
相关推荐
评论
共 6 条评论,欢迎与作者交流。
正在加载评论...