总结

又是一日爆炸

\(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);
}

最新文章

  1. Android 通过JNI实现守护进程,使得Service服务不被杀死
  2. win7 64位4GB内存下 tomcat7扩大内存
  3. Java上传文件
  4. 优化后的 google提供的汉字转拼音类(针对某些htc等手机的不兼容情况)
  5. Navi.Soft30.框架.Mobile.开发手册
  6. BFGS方法
  7. Populating Next Right Pointers in Each Node
  8. 在word中做复选框打对勾钩
  9. 【LeetCode】231 - Power of Two
  10. 【转】IT职场人生系列之四:怎样写简历
  11. CGFloat,CGPoint,CGSize,CGRect
  12. bat文件自动编译InnoSetup脚本
  13. 2014web面试题
  14. JS获得一个对象的所有属性和方法
  15. 02_Linux学习_命令
  16. .net c#将数据库数据对象转换为实体值对象
  17. Redis集群管理
  18. 新增和编辑clob字段
  19. 页面仔初窥&quot;前端工程化&quot;
  20. SSH框架搭建过程详解

热门文章

  1. B-神经网络模型复杂度分析
  2. 设计链表-LeetCode707 基础题
  3. 基于 RocketMQ 的 Dubbo-go 通信新范式
  4. form表单里的button 等元素不能使用margin: 0 auto;
  5. TIE: A Framework for Embedding-based Incremental Temporal Knowledge Graph Completion 增量时序知识图谱补全论文解读
  6. 无人机集群的分布式协作 VI-SLAM
  7. SQLMap入门——获取数据库的所有用户
  8. formly-form 动态表单
  9. java中的复合赋值运算符
  10. week_7