D - Ears

题目链接:D - Ears

大意:你在一个\(0-L\)的数轴上行走,从整数格出发,在整数格结束,可以在整数格转弯。每当你经过坐标为\(i-0.5\)的位置时(\(i\)是整数),在\(i\)的位置放置一个石子。现在给出最后的石子序列,但这个序列有可能是不合法的,定义一次操作是将第\(i\)个位置上记录的石子\(-1\)或\(+1\),求最少的操作数使得给定序列成为一个合法序列

分析:

我们记录一次行走的起点为\(S\),终点为\(T\),在这次行走中到达的最左边的点为\(L\),最右边的点为\(R\)

那么这四个点将坐标轴分成了五个部分

(1):\(0\text~L-1\),\(A_i=0\)

(2):\(L\text~S-1\),\(A_i\)为偶数(可以为0)

(3):\(S\text ~T\),\(A_i\)为奇数

(4):\(T+1\text~ R\),\(A_i\)为偶数(可以为0)

(5):\(R+1\text~ INF\),\(A_i=0\)

那么我们可以进行dp,记\(dp[i][j]\)表示在第\(i\)号格子中时属于第\(j\)个部分

每一次从\(i-1\)号格子中的\(\leq j\)的部分的最小值转移而来

注意在2,3,4部分中,如果\(A_i=0\)的话任然需要计算花费(为了到达下一个部分)

似乎可以滚动数组优化(但是懒qwq)

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
#include<queue>
#include<map>
using namespace std;
const int maxd=1000000007,N=100000;
const double pi=acos(-1.0);
typedef long long ll;
int n;
ll a[200200],dp[200200][5]; int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
} int main()
{
n=read();int i;
for (i=1;i<=n;i++) a[i]=read();
for (i=1;i<=n;i++)
{
ll mind=dp[i-1][0];
dp[i][0]=dp[i-1][0]+a[i];
mind=min(mind,dp[i-1][1]);
if (a[i]) dp[i][1]=mind+(a[i]%2);else dp[i][1]=mind+2;
mind=min(mind,dp[i-1][2]);
if (a[i]) dp[i][2]=mind+((a[i]+1)%2);else dp[i][2]=mind+1;
mind=min(mind,dp[i-1][3]);
if (a[i]) dp[i][3]=mind+(a[i]%2); else dp[i][3]=mind+2;
mind=min(mind,dp[i-1][4]);
dp[i][4]=mind+a[i];
}
ll ans=min(min(dp[n][2],dp[n][3]),dp[n][4]);
printf("%lld",ans);
return 0;
}

E - Odd Subrectangles

题目链接:E - Odd Subrectangles

大意:给出一个\(n\)行\(m\)列的01矩阵,你可以选定一个行集合和列集合,使得那些行数和列数均在对应集合的矩阵中的位置上的数字之和是奇数,求方案数(感觉翻译的好奇怪啊QAQ,算了意思到了(逃)

分析:

将问题转化,“和为奇数”等价于“异或和为1”

将每一行都视作一个数(\(< 2^m\)),我们考虑已经选择了任意的\(i\)行

首先如果说我们选定的这\(i\)行的异或之和为0的话,无论我们怎么选择列,选定格子的异或之和均为0

所以此时对应的方案数为0

那么如果这\(i\)行的异或和不为0的话,就说明是01交杂的

我们假设最后的异或和存在\(a\)个\(1\)和\(b\)个\(0\),那么首先就有\(a+b=m\)

同时要使所有选择的格子异或之和为奇数的话,那么我们一定会选择奇数个\(1\),而\(0\)的个数是任意的

选择\(1\)的方案数:\(C^1_a+C^3_a+\cdots+C^a_a(a\text%2=1)(或C_a^{a-1}当a\text%2=0)=2^{a-1}\)

(利用二项式定理和组合数的递推证明)

选择\(0\)的方案数:\(2^b\)

所以对于这\(i\)行而言合法的选择方案为\(2^{a-1}*2^b=2^{a+b-1}=2^{m-1}\)

我们发现,无论\(i\)的值是多少以及我们如何选取这\(i\)行,最后选取的列的方案数是一定的

由于异或和不为\(0\)的方案数=总方案数-异或和为0的方案数

所以\(ans=(2^n-行异或和为0的方案数)*2^{m-1}\)

行异或和的方案数可以用\(bitset+\)线性基完成,记最后被赋了值的线性基总数为\(x\)

则\(ans=(2^n-2^{n-r})*2^{m-1}\)(对于剩下的\(n-r\)个未被插入线性基的数,我们可以选取它和可以表示它的线性基里面的数)

直接预处理2的幂次即可

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
#include<queue>
#include<bitset>
#include<map>
using namespace std;
const int maxd=998244353,N=100000;
const double pi=acos(-1.0);
typedef long long ll;
int n,m,cnt=0;
ll bin[320];
bitset<320> a[320],p[320]; int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
} int main()
{
n=read();m=read();
int i,j;
bin[0]=1;
for (i=1;i<=300;i++) bin[i]=(bin[i-1]*2)%maxd;
for (i=1;i<=n;i++)
{
for (j=1;j<=m;j++)
{
int tmp=read();
if (tmp) a[i][j]=1;
}
}
for (i=1;i<=n;i++)
{
for (j=1;j<=m;j++)
{
if (a[i][j])
{
if (p[j][j]) a[i]^=p[j];
else
{
p[j]=a[i];
cnt++;
break;
}
}
}
}
ll ans=(((bin[n]-bin[n-cnt])*bin[m-1])%maxd+maxd)%maxd;
printf("%lld",ans);
return 0;
}

F - Pass

题目链接:F - Pass

题目大意:\(n\)个人站成一排,开始时每个人手上有两个球(红色或蓝色),在每一个时刻第\(i\)个人如果手上有球就随机把一个球传给第\(i-1\)个人,第\(1\)个人传给小明,小明记录下球的颜色,问最后有可能记录下的球的颜色序列有多少种?

难得F比E还简单(虽然我没有做出来)

预处理\(1-i\)个人手上有几个红球几个蓝球

记\(dp[i][j]\)表示已经记录了\(i\)个球的颜色,其中\(j\)个是红球

转移十分显然:\(dp[i][j]=dp[i-1][j]+dp[i-1][j-1]\)

注意一下当前的红球数为\(j\),蓝球数为\(i-j\)

而在枚举\(i​\)的时候红球和蓝球个数均有一个上界,不能超过这个上界

同时\(j-1\geq 0\)即可

\(ans=dp[2*n][红球个数]\)

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
#include<queue>
#include<map>
using namespace std;
const int maxd=998244353,N=100000;
const double pi=acos(-1.0);
typedef long long ll;
int n,sumr[3030],sumb[3030],dp[4060][4060];
char s[3030]; int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
} int main()
{
scanf("%s",s+1);
int i,j;n=strlen(s+1);
sumr[0]=0;sumb[0]=0;
for (i=1;i<=n;i++)
{
sumr[i]=sumr[i-1];sumb[i]=sumb[i-1];
if (s[i]=='0') sumr[i]+=2;
else if (s[i]=='1') {sumr[i]++;sumb[i]++;}
else if (s[i]=='2') sumb[i]+=2;
}
//for (i=1;i<=n;i++) cout << sumr[i] << " ";cout << endl;
//for (i=1;i<=n;i++) cout << sumb[i] << " ";cout << endl;
dp[0][0]=1;
for (i=1;i<=2*n;i++)
{
int nowr=sumr[min(i,n)],nowb=sumb[min(i,n)];
for (j=0;j<=i;j++)
{
if ((nowr>=j) && (nowb>=i-j))
{
dp[i][j]=dp[i-1][j];
if (j>0) dp[i][j]=(dp[i][j]+dp[i-1][j-1])%maxd;
}
}
}
printf("%lld",dp[2*n][sumr[n]]);
return 0;
}

每次做AtCoder的题都能感觉到自己的渺小

Yahoo Programming Contest 2019 补题记录(DEF)的更多相关文章

  1. [AtCoder] Yahoo Programming Contest 2019

    [AtCoder] Yahoo Programming Contest 2019   很遗憾错过了一场 AtCoder .听说这场是涨分场呢,于是特意来补一下题. A - Anti-Adjacency ...

  2. 【AtCoder】Yahoo Programming Contest 2019

    A - Anti-Adjacency K <= (N + 1) / 2 #include <bits/stdc++.h> #define fi first #define se se ...

  3. Yahoo Programming Contest 2019 自闭记

    A:签到. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> ...

  4. Yahoo Programming Contest 2019.F.Pass(DP)

    题目链接 惊了这是什么F题...怎么我都能做出来...以后atcoder的比赛也不能走神了万一有个这样的F呢(CF已有多次了= =) \(f[i][j]\)表示Takahashi现在一共有\(i\)个 ...

  5. Yahoo Programming Contest 2019.E.Odd Subrectangles(思路 线性基)

    题目链接 \(Description\) 给定一个\(n\times m\)的\(01\)矩阵.求任意选出\(r\)行.\(c\)列(共\(2^{n+m}\)种方案),使得这\(r\)行\(c\)列的 ...

  6. Yahoo Programming Contest 2019.D.Ears(DP)

    题目链接 菜爆了啊QAQ 记起点为\(S\),终点为\(T\),走过的最靠左的点是\(L\),最靠右的点是\(R\). 那么坐标轴被分成了五段: \(0\sim L-1\):经过\(0\)次: \(L ...

  7. Yahoo Programming Contest 2019 E - Odd Subrectangles

    E - Odd Subrectangles 思路: 对于行方案固定的情况下,假设和为奇数的列为a个,和为偶数的列为b个,a+b = m 那么从奇数里面选奇数个,即C(a, 1) + C(a, 3) + ...

  8. Yahoo Programming Contest 2019 F - Pass

    F - Pass 思路: dp[i][j] 表示到第 i 个球为止放了 j 个蓝球的方案数 第 i 个球来自的位置的最右边是min(i, n) 转移方程看代码 代码: #pragma GCC opti ...

  9. Yahoo Programming Contest 2019 D - Ears

    D - Ears 思路: s:起点           t:终点           l:左端点           r:右端点 以上称为关键点 dp[i][j]表示到位置 i 为止,已经经过前 j ...

随机推荐

  1. 二十:让行内元素在div中垂直居中

    (1)使用display:table-cell配合vertical-align:center(淘宝也是这样用的) <div class="method4"> <s ...

  2. js判断浏览器的类型,动态调整div布局

    最近写页面用bootstrap和amazeUi然后发现自己写的部分和两个框架做重合时,页面大小变化后有的元素变得很乱,很乱无奈只好用js判断 window.onscroll = function sc ...

  3. Python—函数的名称空间

    名称空间 又名name space, 顾名思义就是存放名字的地方,存什么名字呢?举例说明,若变量x=1,1存放于内存中,那名字x存放在哪里呢?名称空间正是存放名字x与1绑定关系的地方 名称空间共3种, ...

  4. python中变量、函数、类名、模块名等命名方式

    摘要:模块名:小写字母,单词之间用_分割ad_stats.py包名:和模块名一样类名:单词首字母大写AdStatsConfigUtil全局变量名(类变量,在java中相当于static变量):大写字母 ...

  5. 【学习总结】Git学习-参考廖雪峰老师教程三-创建版本库

    学习总结之Git学习-总 目录: 一.Git简介 二.安装Git 三.创建版本库 四.时光机穿梭 五.远程仓库 六.分支管理 七.标签管理 八.使用GitHub 九.使用码云 十.自定义Git 期末总 ...

  6. 数组建 BST

    #include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; int N, root = 1; int ...

  7. js-XMLHttpRequest 2级

    ###1. XMLHttpRquest 2级 1)   FormData 现代web应用中频繁使用的一项功能就死表单数据的序列化, XMLHttpRquest 2级为此定义了FormData类型 Fo ...

  8. vue路由的知识点

    this.$router.push({name:'login',query:{name:'ww',age:18}}) 传数据 this.$route.query 拿数据 meta:{ "dl ...

  9. checkbox的使用总结,判断是否选中

    方法一: if ($("#checkbox-id").get(0).checked) { // do something } 方法二: if($('#checkbox-id').i ...

  10. Oracle Flashback 详解

    Oracle flashback 是一种方便快捷的数据库恢复技术,它不使用备份文件,通过闪回日志可以使数据库恢复到过去的某个状态,当用户发生逻辑错误时(误删表数据.表.表空间等)需要快速恢复数据库,可 ...