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. 百度软件开发实习生c++方向面经(一面)

    百度2017实习生软件开发(cpp方向) 首先说一下岗位.分为软件开发,开发测试,前端,机器学习数据挖掘,移动开发,据我观察,报的人数来看,软件开发最多,移动开发和开发测试较少.百度前台还准备了吃的喝 ...

  2. Python—re模块

    re模块 正则表达式就是字符串的匹配规则,在多数编程语言里都有相应的支持,python里对应的模块是re 常用的表达式规则 '.' 默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹 ...

  3. 使用faker去构造一个User-Agent

    faker可以仿造各种各样的信息,可以使用faker去构造一个User-Agent from faker import Factory f = Factory.create() 'User-Agent ...

  4. Form的is_valid校验规则及验证顺序

    一.验证顺序   查看form下的源码了解顺序 BaseForm为基类,中间包含了is_valid校验方法 @html_safe class BaseForm: ......... self.is_b ...

  5. 学习yii2.0——行为

    学习yii框架的行为之前,需要先了解yii的事件,可以参考这篇博客: 怎么理解行为 yii框架的行为有点类似于trait,可以有个大体的概念: 1.有一个类A,包含一些属性和方法,很普通的一个类A. ...

  6. java kill thread command line

    multithreading - How do you kill a Thread in Java? - Stack Overflowhttps://stackoverflow.com/questio ...

  7. laravel get和all区别

      get ,all 都可以获取到模型 all 是直接获取所有,get 是在添加了许多约束之后获取模型,get前面如果不加约束条件的话,效果与all等同

  8. springmvc通过HttpServletRequest进行参数传递

    @RequestMapping("/itemEdit") public String itemEdit(HttpServletRequest request, Model mode ...

  9. Linux基础学习笔记2-文件管理和重定向

    本节内容 1)文件系统结构元素 2)创建和查看文件 3)复制.转移和删除文件 4)软和硬链接 5)三种I/O设备 6)把I/O重定向至文件 7)使用管道 文件系统和结构 文件系统 文件和目录被组织成一 ...

  10. Hbase存储思想