JZOJ 2020.08.03【NOIP提高组】模拟 &&【NOIP2015模拟11.5】
总结
又是一日爆炸
不出所料报 了?!
题目
JZOJ 4315. Prime
暴力就好了?!
考场根本没想暴力
赛后发现暴力跑得贼快
只需二分一下组数的上界
然后 判断能否能成功分完组
跑时顺便统计答案就行了
#include<cstdio> #include<iostream> using namespace std; const int N = 20; int n , a[N] , vis[N][N] , d[N][N] , cnt , ans , Mx , bz; inline int gcd(int x , int y){return y == 0 ? x : gcd(y , x % y);} inline void dfs(int x , int mid , int Max) { if (mid > ans || mid == ans && Max >= Mx) return; if (cnt > mid) return; if (x > n) { bz = 1; if (ans > mid) ans = mid , Mx = Max; else if (ans == mid && Max < Mx) Mx = Max; return; } for(register int i = 1; i <= cnt; i++) { int fl = 0; for(register int j = 1; j <= d[i][0]; j++) if (!vis[x][d[i][j]]) { fl = 1; break; } if (fl) continue; d[i][++d[i][0]] = x; dfs(x + 1 , mid , max(Max , d[i][0])); --d[i][0]; } d[++cnt][++d[cnt][0]] = x; dfs(x + 1 , mid , max(Max , 1)); --d[cnt][0] , --cnt; } int main() { freopen("prime.in" , "r" , stdin); freopen("prime.out" , "w" , stdout); scanf("%d" , &n); for(register int i = 1; i <= n; i++) scanf("%d" , &a[i]); for(register int i = 1; i <= n; i++) for(register int j = 1; j <= n; j++) if (i != j) vis[i][j] = gcd(a[i] , a[j]) == 1 ? 1 : 0; ans = 0x3f3f3f3f , Mx = 0x3f3f3f3f; int l = 1 , r = n , mid; while (l <= r) { mid = (l + r) >> 1; cnt = bz = 0; dfs(1 , mid , 0); if (bz) r = mid - 1; else l = mid + 1; } printf("%d %d" , ans , Mx); }
JZOJ 4316. Isfind
一眼没看出?!序列自动机?!?
去一边,暴力又能过?!!
天!!!
而我想到了非暴力的解法,幸好过了,不然亏大了
只需记录每种字母在原串出现的先后位置
然后匹配时二分找位置判断就行了
#include<cstdio> #include<cstring> using namespace std; const int N = 1e5 + 5; int n , m , a[30][N] , p[30]; char s[N]; inline int binary(int t , int x) { int l = 0 , r = p[t] , mid , res = -1; while (l <= r) { mid = (l + r) >> 1; if (a[t][mid] >= x) res = a[t][mid] , r = mid - 1; else l = mid + 1; } return res; } int main() { freopen("isfind.in" , "r" , stdin); freopen("isfind.out" , "w" , stdout); scanf("%d%d%s" , &n , &m , s); int len = strlen(s) , pos , pos1 , fl; for(register int i = 0; i < 28; i++) p[i] = -1; for(register int i = 0; i < len; i++) a[s[i] - 'a'][++p[s[i] - 'a']] = i; while (m--) { scanf("%s" , s); len = strlen(s); pos = -1; fl = 0; for(register int i = 0; i < len; i++) { pos1 = binary(s[i] - 'a' , pos + 1); if (pos1 == -1) { printf("N\n"); fl = 1; break; } else pos = pos1; } if (!fl) printf("Y\n"); } }
实际上,它是序列自动机的模板题
所以上个序列自动机的代码
#include<cstdio> #include<cstring> using namespace std; const int N = 1e5 + 5 , INF = 0x3f3f3f3f; int n , m , nxt[N][30]; char s[N]; int main() { freopen("isfind.in" , "r" , stdin); freopen("isfind.out" , "w" , stdout); scanf("%d%d%s" , &n , &m , s); int len = strlen(s); for(register int i = 0; i <= 26; i++) nxt[len][i] = INF; for(register int i = len - 1; i >= 0; i--) { for(register int j = 0; j <= 26; j++) nxt[i][j] = nxt[i + 1][j]; nxt[i][s[i] - 'a'] = i; } for(; m; --m) { scanf("%s" , s); len = strlen(s); int pos = -1 , fl = 0; for(register int i = 0; i < len; i++) { pos = nxt[pos + 1][s[i] - 'a']; if (pos == INF) { printf("N\n") , fl = 1; break; } } if (!fl) printf("Y\n"); } }
JZOJ 4317. Divide
很显然 有用的部分是
然后我们就发现 相当于 的因数相乘
我们只要处理出 的所有因数,然后 枚举三个因数相乘
用桶记下每种因数在 出现的次数
然后分类讨论算贡献即可
#include<cstdio> using namespace std; typedef long long LL; const int N = 3e4 + 5 , M = 1e6 + 5; LL a[N] , pr[M] , buc[M] , p , ans; int n , tot; inline LL gcd(LL x , LL y){return y == 0 ? x : gcd(y , x % y);} int main() { freopen("divide.in" , "r" , stdin); freopen("divide.out" , "w" , stdout); scanf("%d%lld" , &n , &p); for(register int i = 1; i <= n; i++) { scanf("%lld" , &a[i]); a[i] = gcd(a[i] , p); ++buc[(int)a[i]]; } for(register int i = 1; i <= p; i++) if (p % i == 0) pr[++tot] = i; for(register int i = 1; i <= tot; i++) for(register int j = i; j <= tot; j++) for(register int k = j; k <= tot; k++) if (pr[i] * pr[j] % p * pr[k] % p == 0) { if (i == j && i == k) ans += buc[pr[i]] * (buc[pr[i]] - 1) * (buc[pr[i]] - 2) / 6; else{ if (i == j) ans += buc[pr[i]] * (buc[pr[j]] - 1) * buc[pr[k]] / 2; else if (i == k) ans += buc[pr[i]] * (buc[pr[k]] - 1) * buc[pr[j]] / 2; else if (j == k) ans += buc[pr[j]] * (buc[pr[k]] - 1) * buc[pr[i]] / 2; else ans += buc[pr[i]] * buc[pr[j]] * buc[pr[k]]; } } printf("%lld" , ans); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具