A:mine

只是一个简单的dp。。。。是博主太蒻了。。。

设f[i][j],表示到第i位,状态是j的方案数,其中$j\in[0,5]$

j==0表示填0,j==1表示填1,且i-1位是雷;

j==2表示填2,j==3表示填雷,j==5表示填1,且i-1位不是雷

思考一下,得到方程:

      $f[i][4]=f[i-1][3]$
            $f[i][1]=f[i-1][4]+f[i-1][0]$

      $f[i][3]=f[i-1][1]+f[i-1][2]+f[i-1][3]$
            $f[i][0]=f[i-1][4]+f[i-1][0]$
            $f[i][2]=f[i-1][3]$

然后就没什么了

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define int long long
using namespace std;
const int MAXN=1e6+1;
const int mod=1e9+7;
int len,ans=0,f[2][5];
char s[MAXN];
signed main(){
scanf("%s",s+1);
len=strlen(s+1);
if(s[1]=='*') f[1][3]=1;
else if(s[1]=='1') f[1][1]=1;
else if(s[1]=='0') f[1][0]=1;
else if(s[1]=='?') f[1][3]=f[1][1]=f[1][0]=1;
for(int i=2;i<=len;i++){
f[i&1][0]=f[i&1][1]=f[i&1][2]=f[i&1][3]=f[i&1][4]=0;
if(s[i]=='?'){
f[i&1][4]=f[i&1^1][3]%mod;
f[i&1][1]=(f[i&1^1][4]+f[i&1^1][0])%mod;
f[i&1][3]=((f[i&1^1][1]+f[i&1^1][2])%mod+f[i&1^1][3])%mod;
f[i&1][0]=(f[i&1^1][4]+f[i&1^1][0])%mod;
f[i&1][2]=f[i&1^1][3]%mod;
}else if(s[i]=='1'){
f[i&1][4]=f[i&1^1][3]%mod;
f[i&1][1]=(f[i&1^1][4]+f[i&1^1][0])%mod;
}else if(s[i]=='*'){
f[i&1][3]=((f[i&1^1][1]+f[i&1^1][2])%mod+f[i&1^1][3])%mod;
}else if(s[i]=='0'){
f[i&1][0]=(f[i&1^1][4]+f[i&1^1][0])%mod;
}else{
f[i&1][2]=f[i&1^1][3]%mod;
}
}
ans=((f[len&1][4]+f[len&1][0])%mod+f[len&1][3])%mod;
printf("%lld\n",ans);
return 0;
}

B:water

一个块的高度就是从这个块走出矩形的所有路径上的最大值的最小值。

相邻块连边,权值为两块的较大值,矩形边界的块向“矩形外”连边,权值为 max(高度,0),

做最小生成树,然后每个点的积水高度就是这个点到根节点路径上的最大边权减去这个点的点权

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 305
#define inf 0x7fffffff
using namespace std;
int n,m,a[MAXN][MAXN],dep[MAXN*MAXN];
int calc(int i,int j){
return (i-1)*m+j;
}
struct node{
int fr,to,w,nxt;
friend bool operator < (node a,node b){
return a.w<b.w;
}
}e[MAXN*MAXN*4],edge[MAXN*MAXN*4];
int pre[MAXN*MAXN],cnt=0,tot=0;
void add(int u,int v,int w){
cnt++;
e[cnt].to=v,e[cnt].fr=u;
e[cnt].w=w;
}
void ADD(int u,int v,int w){
tot++;
edge[tot].to=v,edge[tot].fr=u;
edge[tot].nxt=pre[u],pre[u]=tot;
edge[tot].w=w;
}
int fa[MAXN*MAXN];
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
void kruskal(){
for(int i=1;i<=n*m+1;i++) fa[i]=i;
sort(e+1,e+cnt+1);
int sum_edge=0,sum=0;
for(int i=1;i<=cnt;i++){
int x=find(e[i].fr),y=find(e[i].to);
if(x!=y){
fa[x]=y;
ADD(x,y,e[i].w);
ADD(y,x,e[i].w);
sum_edge++;
}
if(sum_edge==n*m)
break;
}
}
bool vis[MAXN*MAXN];
void dfs(int x,int fa){
vis[x]=1;
for(int i=pre[x];i;i=edge[i].nxt){
int y=edge[i].to;
if(y==fa) continue;
if(vis[y]) continue;
dep[y]=max(dep[x],max(dep[y],edge[i].w));
dfs(y,x);
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(j+1<=m){
add(calc(i,j),calc(i,j+1),max(a[i][j],a[i][j+1]));
add(calc(i,j+1),calc(i,j),max(a[i][j],a[i][j+1]));
}
if(i+1<=n){
add(calc(i,j),calc(i+1,j),max(a[i][j],a[i+1][j]));
add(calc(i+1,j),calc(i,j),max(a[i][j],a[i+1][j]));
}
}
}
for(int i=1;i<=m;i++){
add(n*m+1,calc(1,i),max(0,a[1][i]));
add(calc(1,i),n*m+1,max(0,a[1][i]));
add(n*m+1,calc(n,i),max(0,a[n][i]));
add(calc(n,i),n*m+1,max(0,a[n][i]));
}
for(int i=2;i<n;i++){
add(n*m+1,calc(i,1),max(0,a[i][1]));
add(calc(i,1),n*m+1,max(0,a[i][1]));
add(n*m+1,calc(i,m),max(0,a[i][m]));
add(calc(i,m),n*m+1,max(0,a[i][m]));
}
kruskal();
memset(dep,-0x7f,sizeof(dep));
dfs(n*m+1,0);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
printf("%d ",dep[calc(i,j)]-a[i][j]);
}
puts("");
}
return 0;
}

C:gcd

并不是gcd,好像有mobius反演的内容,博主先咕了

不能咕!只知道按着题解说的做,它说啥我做啥

用 f(i)表示 gcd 为 i 的数对个数,g(i)表示 gcd 为 i 的倍数的数对个数。

那么$f(i)=\sum\limits_d\mu(d)*g(d)$,我们只需要维护g(1)~g(max(xi))。

记 s(i)表示 i 的倍数的个数,那么$g(i)=\frac{s(i)*(s(i)-1)}{2}$,

我们只需要在加入/删除一个数时枚举它的因数修改 s 即可。

下面放上我的濒临TLE代码:

第一遍TLE70,原封不动再交一遍就A了

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#define MAXN 200005
#define MAXX 500005
#define int long long
using namespace std;
int n,m,maxa=0,a[MAXN];
int prime[MAXX],vis[MAXX],mu[MAXX],tot;
void get_mu(int n){
vis[1]=mu[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i]) prime[++tot]=i,mu[i]=-1;
for(int j=1;j<=tot&&i*prime[j]<=n;j++){
vis[i*prime[j]]=1;
if(!(i%prime[j])){
mu[i*prime[j]]=0;
break;
}
mu[i*prime[j]]=-mu[i];
}
}
}
vector<int>d[MAXX];
bool flag[MAXN];
int f,g[MAXX],s[MAXX];
void add(int x){
int N=d[x].size();
for(int i=0;i<N;i++){
int t=d[x][i];
s[t]++;
f-=mu[t]*g[t];
g[t]=s[t]*(s[t]-1)/2;
f+=mu[t]*g[t];
}
}
void del(int x){
int N=d[x].size();
for(int i=0;i<N;i++){
int t=d[x][i];
s[t]--;
f-=mu[t]*g[t];
g[t]=s[t]*(s[t]-1)/2;
f+=mu[t]*g[t];
}
}
signed main(){
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
maxa=max(maxa,a[i]);
}
get_mu(maxa);
for(int i=1;i<=maxa;i++)
for(int j=1;j*i<=maxa;j++)
d[i*j].push_back(i);
for(int i=1,pos;i<=m;i++){
scanf("%lld",&pos);
if(!flag[pos]) add(a[pos]);
else del(a[pos]);
printf("%lld\n",f);
flag[pos]=!flag[pos];
}
return 0;
}

HZOI20190816模拟23 mine/water/gcd的更多相关文章

  1. NOIP模拟测试23「mine·water·gcd」

    mine 题解 一道比较水的dp 考试因为初始化挂掉了只有$80$分 代码有注释 #include<bits/stdc++.h> using namespace std; //无脑dp # ...

  2. noip模拟23[联·赛·题]

    \(noip模拟23\;solutions\) 怎么说呢??这个考试考得是非常的惨烈,一共拿了70分,为啥呢 因为我第一题和第三题爆零了,然后第二题拿到了70分,还是贪心的分数 第一题和第二题我调了好 ...

  3. [考试总结]noip模拟23

    因为考试过多,所以学校的博客就暂时咕掉了,放到家里来写 不过话说,vscode的markdown编辑器还是真的很好用 先把 \(noip\) 模拟 \(23\) 的总结写了吧.. 俗话说:" ...

  4. [NOIP模拟23]题解

    中间鸽了好几篇啊QAQ……有时间再补吧…… A.mine sbdp,考场上写的巨麻烦不过还是能A的(虽然MLE了……每一维都少开1就A掉了555).设$dp[i][j][k]$为枚举到第i位,第i位是 ...

  5. BestCoder Round #75 King&#39;s Cake 模拟&amp;&amp;优化 || gcd

    King's Cake Accepts: 967 Submissions: 1572 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 6553 ...

  6. 11.12模拟考T2(GCD)

    2.梅花桩   (blossom.pas/c/cpp) [问题描述] 小x在练习一门轻功,这门轻功是在梅花桩上跳来跳去,这门轻功是严格按照直线从一个梅花桩直接跳到另外一个梅花桩上.因为小x有恐高症,所 ...

  7. NOIP模拟 23

    曾经有一段真挚的AK摆在skyh面前,但他一直意淫自己AK导致没有AK. 如果非要把这AK加一个期限的话,skyh一辈子都AK不了了. 论爆零选手的爆零原因 我说T3想到了能AC的思路但是爆零了有人同 ...

  8. Qbxt 模拟赛 Day4 T2 gcd(矩阵乘法快速幂)

    /* 矩阵乘法+快速幂. 一开始迷之题意.. 这个gcd有个规律. a b b c=a*x+b(x为常数). 然后要使b+c最小的话. 那x就等于1咯. 那么问题转化为求 a b b a+b 就是斐波 ...

  9. [NOIP2019模拟赛]数数(gcd)

    题目大意: 求l~r中有多少数与x互质,带单点修改 分析: 两个30的部分分很好打: ·n<=1000暴力O(nq)就好了 ·$a_i<=100$用树状数组维护每个x的前缀和就好了 100 ...

随机推荐

  1. jQuery 表单域选中选择器

    复选框.单选按钮.下拉列表 /***********************************************/ <script type="text/javascrip ...

  2. 剑指offer——20删除链表中重复的结点

    题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5 处理后 ...

  3. 剑指offer——01数组中重复的数字

    题目描述 在一个长度为n的数组里的所有数字都在0到n-1的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一个重复的数字. 例如,如果输入长度为 ...

  4. Python分布式爬虫必学框架scrapy打造搜索引擎✍✍✍

    Python分布式爬虫必学框架scrapy打造搜索引擎  整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课程本身 ...

  5. Word 多级节标题设置和图表章节号自动生成

    写文章的时候,正文.图表.节标题,通过“样式”可以进行统一设置,这里我记录了几点小技巧: 1.多级标题如何设置 假设我要设置三级标题,下面以图的形式记录方式: 设置完之后,应用即可. 章节设定之后,可 ...

  6. html编写的日历

    1.html (1) <html> <head> <meta http-equiv="Content-Type" content="text ...

  7. Web安全之跨站伪造请求(CSRF)

    CSRF简介 CSRF全称跨站伪造请求(Cross-site request forgery)也称为one click attack/session riding,还可以缩写为XSRF 通俗说就是利用 ...

  8. IDEA引入jar但无法导入class

    如图,jar已经导入,但是无法import class 选择setting->maven->Ignored Files,将被忽略的model取消选中就可以解决了

  9. VS2010-MFC(文档、视图和框架:分割窗口)

    转自:http://www.jizhuomi.com/software/226.html 上一节讲了文档.视图和框架结构中各对象之间的关系,本节主要讲讲在MFC中如何分割窗口. 分割窗口概述      ...

  10. PAT甲级——A1118 Birds in Forest【25】

    Some scientists took pictures of thousands of birds in a forest. Assume that all the birds appear in ...