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. day 89 DjangoRestFramework学习三之认证组件、权限组件、频率组件、url注册器、响应器、分页组件

    DjangoRestFramework学习三之认证组件.权限组件.频率组件.url注册器.响应器.分页组件   本节目录 一 认证组件 二 权限组件 三 频率组件 四 URL注册器 五 响应器 六 分 ...

  2. 专题:“find -perm”

    Search for files which have read and write permission for their owner, and group, but which other us ...

  3. Git 学习(二)Git 基础

    Git 基础 Git 在保存和对待各种信息的时候与其它版本控制系统如 SVN 等等有很大差异,尽管操作起来的命令形式非常相近,理解这些差异将有助于防止你使用中的困惑. Git 记录的是什么? 如果有使 ...

  4. Windows下安装配置PLSQL

    说明:1.PLSQL Developer是远程连接Oracle数据库的一个可视化工具,并且其不是一个独立的软件,是需要依赖Oracle客户端运行的.2.本安装教程是基于本机没有安装Oracle数据库的 ...

  5. 02ubuntu下python环境安装

    原文链接:https://blog.csdn.net/weixin_42549407/article/details/85198460 我安装的是python3.6.9 1.下载python的源码压缩 ...

  6. 计算a,b,c的排列组合

    递归实现,思路的确有点难得想: public void SortAll(List<string> list,int start,int end) { if (start==end) { f ...

  7. UC浏览器禁止图片阅读模式处理方法

    本文转载自:https://www.cnblogs.com/MY0101/p/9969818.html UC浏览器点击图片会出现图片阅读模式. 如何处理? <img style=" w ...

  8. ubuntu下安装git提示无root权限

    apt-get install git 获取git指令 sudo passwd root 重置unix密码 su root 键入密码 参考链接 https://www.cnblogs.com/2she ...

  9. 廖雪峰Java16函数式编程-2Stream-6reduce

    1. 聚合方法 Stream.reduce()是一个Stream的聚合方法:把一个Stream的所有元素聚合成一个结果 例如: Stream.of(1, 2, 3, 4, 5).count(); // ...

  10. PHP跨服务器提交数据

    关于类似的问题,百度上一搜一大堆,这只是我自己实际用过的两个方法,不多BB直接上代码 1.第一种: 2.第二种 可以随意切换POST和GET提交方式