JZOJ 2020.08.03【NOIP提高组】模拟 &&【NOIP2015模拟11.5】
2024-09-18 17:19:30
总结
又是一日爆炸
\(T1\) 不出所料报 \(0\) 了?!
题目
\(T1\)
JZOJ 4315. Prime
暴力就好了?!
考场根本没想暴力
赛后发现暴力跑得贼快
只需二分一下组数的上界
然后 \(dfs\) 判断能否能成功分完组
跑时顺便统计答案就行了
\(Code\)
#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);
}
\(T2\)
JZOJ 4316. Isfind
一眼没看出?!序列自动机?!?
去一边,暴力又能过?!!
天!!!
而我想到了非暴力的解法,幸好过了,不然亏大了
只需记录每种字母在原串出现的先后位置
然后匹配时二分找位置判断就行了
\(Code\)
#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");
}
}
实际上,它是序列自动机的模板题
所以上个序列自动机的代码
\(Code\)
#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");
}
}
\(T3\)
JZOJ 4317. Divide
很显然 \(a_i\) 有用的部分是 \(\gcd(a_i,p)\)
然后我们就发现 \(a_i \times a_j \times a_k\) 相当于 \(p\) 的因数相乘
我们只要处理出 \(p\) 的所有因数,然后 \(O(tot^3)\) 枚举三个因数相乘
用桶记下每种因数在 \(a\) 出现的次数
然后分类讨论算贡献即可
\(Code\)
#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);
}
最新文章
- Android 通过JNI实现守护进程,使得Service服务不被杀死
- win7 64位4GB内存下 tomcat7扩大内存
- Java上传文件
- 优化后的 google提供的汉字转拼音类(针对某些htc等手机的不兼容情况)
- Navi.Soft30.框架.Mobile.开发手册
- BFGS方法
- Populating Next Right Pointers in Each Node
- 在word中做复选框打对勾钩
- 【LeetCode】231 - Power of Two
- 【转】IT职场人生系列之四:怎样写简历
- CGFloat,CGPoint,CGSize,CGRect
- bat文件自动编译InnoSetup脚本
- 2014web面试题
- JS获得一个对象的所有属性和方法
- 02_Linux学习_命令
- .net c#将数据库数据对象转换为实体值对象
- Redis集群管理
- 新增和编辑clob字段
- 页面仔初窥";前端工程化";
- SSH框架搭建过程详解
热门文章
- B-神经网络模型复杂度分析
- 设计链表-LeetCode707 基础题
- 基于 RocketMQ 的 Dubbo-go 通信新范式
- form表单里的button 等元素不能使用margin: 0 auto;
- TIE: A Framework for Embedding-based Incremental Temporal Knowledge Graph Completion 增量时序知识图谱补全论文解读
- 无人机集群的分布式协作 VI-SLAM
- SQLMap入门——获取数据库的所有用户
- formly-form 动态表单
- java中的复合赋值运算符
- week_7