11.10 解题报告
T1
考场用时:
期望得分:
实际得分:
直接定义一个分数类,重载 +
和 *
,然后拓扑即可。
#include<bits/stdc++.h>
#define ll __int128
#define int __int128
#define lc(k) k<<1
#define rc(k) k<<1|1
#define lb lower_bound
#define orz puts("gzn ak ioi")
const int MAX=1e5+10;
const int MOD=1e9+7;
using namespace std;
inline char readchar() {
static char buf[100000], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read() {
int res = 0, f = 0;
char ch = readchar();
for(; !isdigit(ch); ch = readchar()) if(ch == '-') f = 1;
for(; isdigit(ch);ch = readchar()) res = (res << 1) + (res << 3) + (ch ^ '0');
return f ? -res : res;
}
inline void write(int x) {
if(x<0){putchar('-');x=-x;}
if(x>9) write(x/10);
putchar(x%10+'0');
}
int n,m,cd[MAX],rd[MAX];// 0 分子 1 分母
int head[MAX],cnt;
struct node{int net,v;}e[MAX*100];
void add(int u,int v){
e[++cnt]=(node){head[u],v};
head[u]=cnt;
return ;
}
struct fs{
int fz,fm;
friend fs operator + (fs x,fs y){
fs ret;
ret.fz=x.fm*y.fz+x.fz*y.fm;
ret.fm=x.fm*y.fm;
int gcd=__gcd(ret.fz,ret.fm);
ret.fz/=gcd;ret.fm/=gcd;
return ret;
}
friend fs operator * (fs x,fs y){
fs ret;
ret.fz=x.fz*y.fz;
ret.fm=x.fm*y.fm;
int gcd=__gcd(ret.fz,ret.fm);
ret.fz/=gcd;ret.fm/=gcd;
return ret;
}
}ans[MAX];
queue<int> q;
void topo(){
for(int i=1;i<=n;i++){
ans[i].fm=1;
if(!rd[i]){
ans[i].fz=1;
q.push(i);
}
}
while(!q.empty()){
int u=q.front();q.pop();
// write(u);puts("");
fs t=(fs){1,cd[u]};
for(int i=head[u];i;i=e[i].net){
int v=e[i].v;
ans[v]=ans[v]+ans[u]*t;
rd[v]--;
if(!rd[v]) q.push(v);
}
}
return ;
}
signed main(){
// freopen("water3.in","r",stdin);
// freopen("1.out","w",stdout);
n=read(),m=read();
for(int i=1;i<=n;i++){
int x=read();
for(int j=1;j<=x;j++){
int v=read();
add(i,v);
cd[i]++;rd[v]++;
}
}
topo();
for(int i=1;i<=n;i++)
if(!cd[i]){
write(ans[i].fz);
putchar(' ');
write(ans[i].fm);
putchar('\n');
}
return 0;
}
T2
考场用时:
期望得分:
实际得分:
发现 第一个 A /唯一的 C 必然分别是一个前缀 / 后缀
预处理 每个位置的 后缀奇数个字符个数(与 C 有关)
每个位置的 前缀奇数个数分别为 i 的位置个数 (与 A 有关),并统计其前缀和
哈希来寻找匹配 AB 这一循环节
#include<bits/stdc++.h>
#define LL long long
#define lc(k) k<<1
#define rc(k) k<<1|1
#define orz cout<<"I AK IOI\n"
//#define int long long
const int MAX=2e5+10;
const int MOD=998244353;
using namespace std;
inline char readchar() {
static char buf[100000], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read() {
#define readchar getchar
int res = 0, f = 0;
char ch = readchar();
for(; !isdigit(ch); ch = readchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = readchar()) res = (res << 1) + (res << 3) + (ch ^ '0');
return f ? -res : res;
}
inline void write(int x) {
if(x<0){putchar('-');x=-x;}
if(x>9) write(x/10);
putchar(x%10+'0');
}
const int Maxc = 30;
const int Maxn = (1 << 20) + 5;
const LL Mod1 = 998244353;
const LL Mod2 = 19260817;
LL hash1[Maxn], hash2[Maxn], pow26[Maxn], Pow26[Maxn];//前缀哈希值
inline void init0() {
pow26[0] = 1;
Pow26[0] = 1;
for(register int i = 1; i < Maxn; ++i) {
pow26[i] = pow26[i - 1] * 26; pow26[i] %= Mod1;
Pow26[i] = Pow26[i - 1] * 26; Pow26[i] %= Mod2;
}
}
inline LL gethash1(int l, int r) {
return ((hash1[r] % Mod1 - 1LL * hash1[l - 1] * pow26[r - l + 1] % Mod1) % Mod1 + Mod1) % Mod1;
}
inline LL gethash2(int l, int r) {
return ((hash2[r] % Mod2 - 1LL * hash2[l - 1] * Pow26[r - l + 1] % Mod2) % Mod2 + Mod2) % Mod2;
}
bool check(int lf, int rt, int l, int r) {
return (gethash1(lf, rt) == gethash1(l, r)) && (gethash2(lf, rt) == gethash2(l, r));
}
int s[Maxn]; // s[i][j]:前 i 个位置有多少个位置奇数个字符不大于 j
int S[Maxn][Maxc];
int bs[Maxn];
int cnt[Maxc];
string str;
int T, ans;
int n, a[Maxn];
void Init() {
ans = 0;
memset(cnt, 0, sizeof(cnt));
memset(bs, 0, sizeof(bs));
memset(s, 0, sizeof(s));
memset(hash1, 0, sizeof(hash1));
memset(hash2, 0, sizeof(hash2));
for(register int i = 1; i <= n; ++i) {
hash1[i] = hash1[i - 1] * 26 % Mod1 + a[i];
hash1[i] %= Mod1;
hash2[i] = hash2[i - 1] * 26 % Mod2 + a[i];
hash2[i] %= Mod2;
}
for(int i = 1; i <= n; ++i) {
cnt[a[i]]++;
if(cnt[a[i]] & 1) s[i] = s[i - 1] + 1;
else s[i] = s[i - 1] - 1;
for(int j = 0; j <= 26; ++j) {
S[i][j] = S[i - 1][j];
if(j >= s[i]) S[i][j]++;
}
}
memset(cnt, 0, sizeof(cnt));
for(int i = n; i >= 1; --i) {
cnt[a[i]]++;
if(cnt[a[i]] & 1) bs[i] = bs[i + 1] + 1;
else bs[i] = bs[i + 1] - 1;
}
return;
}
void mainfunction() {
cin >> str; n = str.size();
for(int i = 0; i < str.size(); ++i) a[i + 1] = (int)str[i] - (int)'a';
Init();
for(int i = 2; i < n; ++i) {
bool flag = 1;
for(int j = i, lt = 1; (j < n) && flag; j += i, lt += i) {
if(check(1, i, lt, j)) {
ans += S[i - 1][bs[j + 1]];
}
else break;
}
}
printf("%d\n", ans);
return;
}
int main() {
init0();
T=read();
while(T--) mainfunction();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术