Problem A  旅行者

有$n$种转移装置,每种转移装置本质相同,每种装置可以前进$a_i$单位,但只有$b_i$个。

从初始坐标为$0$出发,途中不能经过$c_1,c2,...,c_m$中的任意一个点。

走到$\sum\limits_{i = 1}^n a_ib_i$位置的方案数$mod 10^9 + 7$的值。

对于$100\%$的数据满足$1 \leq n \leq 6 , 1 \leq m \leq 10^5 ,0<c_i < \sum\limits_{i = 1}^n a_ib_i$

  Solution :

    由于每个装置本质相同,那么我们只需要记录当前使用的转移装置数作为状态即可。

    这样定义状态的总状态数时$\prod_{i = 1}^n b_i \leq 13^6 = 4826809$

    注意,由于有$m$点不能走,还需要开一个$hash$存当前值能不能走,特殊判掉即可。

    转移的时候枚举当前通过那个转移装置走到当前位置,转移时间复杂度为$O(n)$

    请注意,本题的模数为$10^8 + 7$,您是否数错了零?

    所以,本题的总时间复杂度是$O(n\prod\limits_{i=1}^{n} b_i)$

# pragma GCC optimize()
# include<bits/stdc++.h>
# define int long long
# define hash Hash
# define Rint register int
using namespace std;
const int mo=;
int f[][][][][][];
struct rec{int a,b;}a[];
int n,m;
vector<int>hash[];
inline int read() {
int X=,w=; char c=;
while(c<''||c>'') {w|=c=='-';c=getchar();}
while(c>=''&&c<='') X=(X<<)+(X<<)+(c^),c=getchar();
return w?-X:X;
}
void insert(int key) {
int k = key % ,sz = hash[k].size();
for (int i=;i<sz;i++) if (hash[k][i] == key) return;
hash[k].push_back(key);
}
bool find(int key) {
int k=key % ,sz = hash[k].size();
for (int i=;i<sz;i++) if (hash[k][i] == key) return true;
return false;
}
signed main() {
n=read();
for (Rint i=;i<=n;i++) {
a[i].a=read(); a[i].b=read();
}
m=read();
for (Rint i=;i<=m;i++) {
int t=read(); insert(t);
}
f[][][][][][]=;
for (Rint a1=;a1<=a[].b;a1++) for (Rint a2=;a2<=a[].b;a2++)
for (Rint a3=;a3<=a[].b;a3++) for (Rint a4=;a4<=a[].b;a4++)
for (Rint a5=;a5<=a[].b;a5++) for (Rint a6=;a6<=a[].b;a6++) {
int tmp = a1*a[].a+a2*a[].a+a3*a[].a+a4*a[].a+a5*a[].a+a6*a[].a;
if (find(tmp)) {
f[a1][a2][a3][a4][a5][a6]=;
continue;
}
if (a1+<=a[].b) (f[a1+][a2][a3][a4][a5][a6]+=f[a1][a2][a3][a4][a5][a6])%=mo;
if (a2+<=a[].b) (f[a1][a2+][a3][a4][a5][a6]+=f[a1][a2][a3][a4][a5][a6])%=mo;
if (a3+<=a[].b) (f[a1][a2][a3+][a4][a5][a6]+=f[a1][a2][a3][a4][a5][a6])%=mo;
if (a4+<=a[].b) (f[a1][a2][a3][a4+][a5][a6]+=f[a1][a2][a3][a4][a5][a6])%=mo;
if (a5+<=a[].b) (f[a1][a2][a3][a4][a5+][a6]+=f[a1][a2][a3][a4][a5][a6])%=mo;
if (a6+<=a[].b) (f[a1][a2][a3][a4][a5][a6+]+=f[a1][a2][a3][a4][a5][a6])%=mo;
}
printf("%lld\n",f[a[].b][a[].b][a[].b][a[].b][a[].b][a[].b]%mo);
return ;
}

traveller.cpp

Problem B 序列

定义两个数$(x,y)$是好的,当且仅当$x \leq y$且$x \oplus y$二进制表示下含有奇数个$1$。

现在给出$n$个区间$[l_i,r_i]$,对于每一个$i\in[1,n]$,输出前$i$个区间并中好的数对的个数。

即输出满足下列条件的$(x,y)$的对数。

  • $x,y \in\cup_{j=1}^i [l_j,r_j]$
  • $x\leq y$
  • $x \oplus y$二进制表示下含有奇数个$1$。

对于$100\%$的数据满足$1 \leq n \leq 10^5 , 1\leq l_i\leq r_i\leq 2^{32}-1$

  Solution :

​     首先,$x \oplus y$的二进制表示下有奇数个$1$有充要条件:一个数有偶数个$1$,一个数有奇数个$1$ 。

​     设$x,y$按二进制位写开来,同$1$的数的对数为$w$,那么剩余的奇数个$1$和偶数个$1$都会对答案产生$1$的贡献。

​     如果我们要统计数集$S$中好的数对的个数,我们就只要数一数这个数集中有多少个数含有偶数个$1$,有多少数有奇数个一,即可。最后的答案就是他们两个之积。

​     如何求一个区间$[l,r]$内有多少个数含有奇数个$1$或者偶数个$1$呢。

​     我们只要求前缀和即可,问题转化为求$[1,x]$的答案。

​     观察到一对数$0,1 ; 2, 3 ; 4,5 ... $从$0$开始每两个数一组一定是一个数字含有奇数个$1$,另外一个数字含有偶数个$1$.

​     所以,若$x$是奇数,$[1,x]$的答案直接是$x/2$了; 否则还需要特殊判断$x$这个数字到底是含有奇数个$1$,另外一个数字含有偶数个$1$.

​     接下来的问题就转化为线段的并了,我们可以很方便的用主席树来解决。

​     对值域建动态开点的线段树,当前区间如果被覆盖了直接打上一个$vis$标记,下一次不覆盖当前区间即可。

​     设数的值域是$S$,那么这样做的时间复杂度是$O(n log_2S)$

# pragma GCC optimize()
# include <bits/stdc++.h>
# define int long long
# define lowbit(x) (x&(-x))
const int N=1e5+;
using namespace std;
int n,tot;
inline int read() {
int X=,w=; char c=;
while(c<''||c>'') {w|=c=='-';c=getchar();}
while(c>=''&&c<='') X=(X<<)+(X<<)+(c^),c=getchar();
return w?-X:X;
}
void write(int x) {
if (x<) x=-x,putchar('-');
if (x>) write(x/);
putchar(''+x%);
}
int query(int x) {
if (x&) return x/+;
int ret=,res=x/;
while (x) { x-=lowbit(x); ret^=;}
return res+ret;
}
bool vis[N*];
struct Seg {
int ls,rs,cnt1,cnt2;
}tr[N*];
# define ls tr[x].ls
# define rs tr[x].rs
void update(int &x,int l,int r,int opl,int opr) {
if (!x) x=++tot; if (vis[x]) return;
if (opl<=l && r<=opr) {
vis[x]=;
tr[x].cnt1=query(r)-query(l-);
tr[x].cnt2=r-l+-tr[x].cnt1;
return;
}
int mid=(l+r)>>;
if (opl<=mid) update(ls,l,mid,opl,opr);
if (opr>mid) update(rs,mid+,r,opl,opr);
tr[x].cnt1=tr[ls].cnt1+tr[rs].cnt1;
tr[x].cnt2=tr[ls].cnt2+tr[rs].cnt2;
}
signed main() {
n=read();
int root=;
for (int i=;i<=n;i++) {
int l=read(),r=read();
update(root,,(1ll<<)-,l,r);
write(tr[].cnt1*tr[].cnt2);
putchar('\n');
}
return ;
}

sequence.cpp

Problem C 钢琴家

给出一个基本字符串$S$,给出$n$个目标字符串集合$t_i$。

要求修改一些$S_i$使得可以将$S$划分成一些子串,使得这些子串都在目标字符串集合中出现。

让替换次数尽可能小,且保证存在至少一个最优解。

对于$100\%$的数据,满足 $1 \leq |t_i| \leq |S|\leq 10^3 , 1\leq n\leq 10^2​$

​ Solution :

  本题可以直接用$DP$求出最优策略,设$f[i]$表示匹配到长度$i$的最小代价。

​   枚举一个目标字符串$1 \leq j \leq n$,可以考虑$[i-|t_j|+1 , i]$用串$t_j$来修改。

​   然后计算这样做的代价,就是$\sum\limits_{k = 1}^{|t_j|} [\ S[i-|t_j|+k]\neq t_j[k]\ ]$

​   记录每一次最优的转移是从何而来,这样可以输出方案。

​   最后直接按照最优方案输出即可。

​   时间复杂度为$O(n|S|^2)$

# pragma GCC optimize()
# include <bits/stdc++.h>
using namespace std;
const int N=1e3+;
char t[N][N],s[N];
int n,f[N],len[N];
int pre[N];
int ans[N];
int main() {
scanf("%s",s+);int l=strlen(s+);
scanf("%d",&n);
for (int i=;i<=n;i++) {
scanf("%s",t[i]+);
len[i]=strlen(t[i]+);
}
memset(f,0x3f,sizeof(f)); f[]=;
for (int i=;i<=l;i++)
for (int j=;j<=n;j++) if (i>=len[j]){
int res = ;
for (int k=;k<=len[j];k++) {
if (t[j][k]!=s[i-len[j]+k]) res++;
}
if (f[i-len[j]]+res<f[i]) {
f[i] = f[i-len[j]]+res;
pre[i] = j;
}
}
int now = l;
while (true) {
if (now == ) break;
ans[++ans[]] = pre[now];
now=now-len[pre[now]];
}
for (int i=ans[];i>=;i--) {
for (int j=;j<=len[ans[i]];j++)
putchar(t[ans[i]][j]);
putchar('\n');
}
return ;
}

pianist.cpp

HGOI 20191106 题解的更多相关文章

  1. HGOI 20191106

    HGOI 20191106 t1 旅行家(traveller) 2s,256MB [题目背景] 小X热爱旅行,他梦想有一天可以环游全世界-- [题目描述] 现在小X拥有n种一次性空间转移装置,每种装置 ...

  2. HGOI 20181028 题解

    HGOI 20181028(复赛备考) /* 真是暴力的一天,最后一题MLE?由于数组开得太大了!!! 270滚粗 考场上好像智商高了很多?!(假的) */ sol:暴力求解,然后没有数据范围吐槽一下 ...

  3. HGOI 20190310 题解

    /* 又是又双叒叕WA的一天... 我太弱鸡了... 今天上午打了4道CF */ Problem 1 meaning 给出q组询问,求下列函数的值$ f(a) = \max\limits_{0 < ...

  4. HGOI 20190303 题解

    /* 记一串数字真难. 5435 今天比赛又是hjcAK的一天. 今天开题顺序是312,在搞T1之前搞了T3 昨天某谷月赛真是毒瘤. 但是讲评的同学不错,起码T4看懂了... 构造最优状态然后DP的思 ...

  5. HGOI 20180224 题解

    /* The Most Important Things: ljc chat with fyh on QQTa说期末考Ta数学74分感觉不好但是我觉得fyh是地表最强的鸭~~(of course en ...

  6. HGOI 20190218 题解

    /* 又是AK局... hjc又双叒叕AK了... Hmmm...我侥幸 */ Problem A card 给出无序序列a[]可以选择一个数插入到合适的位置作为一次操作,至少多少次操作后可以把序列变 ...

  7. HGOI 20190217 题解

    /* for me,开训第一天 /beacuse 文化课太差被抓去补文化课了... 看一眼题 : AK局? 但是,Wa on test #10 in problem C 290! (就差那么一咪咪) ...

  8. HGOI 20181103 题解

    problem:把一个可重集分成两个互异的不为空集合,两个集合里面的数相乘的gcd为1(将集合中所有元素的质因数没有交集) solution:显然本题并不是那么容易啊!考场上想了好久.. 其实转化为上 ...

  9. HGOI 20181101题解

    /* 又是爆0的一天(不知道今年高考难不难,反正今天(信息学)真的难!) */ solution:对于两个数相加,有一个显然的结论就是要么不进位(相对于位数大的),要么(进最多一位) 然后对于整个数组 ...

随机推荐

  1. zookeeper集群搭建与升级

    zookeeper 1.zookeeper功能 1-1.配置管理 集中管理配置文件实现服务治理 1-2.命名服务 如为了通过网络访问一个系统,我们得知道对方的IP地址,但是IP地址对人非常不友好,这个 ...

  2. S02_CH16 等精度频率计实验

    S02_CH16 等精度频率计实验 在了解了AXI总线之后,今天我们自己动手设计一个带AXI4-Lite总线的IP,来完成频率计的实验. 频率计虽然小,但是也算五脏俱全,涉及到zynq的方方面面,比如 ...

  3. 解决python在cmd运行时导入包失败,出现错误信息 "ModuleNotFoundError: No module named ***"

    1.下图为我的自动化测试工程结构图 我通过运行run.bat批处理文件,调用cmd控制台运行start_run.py来开始我的自动化测试,但是出现如下错误: 大家可能知道我们的工程在IDE(Pycha ...

  4. hdu 6069 Counting divisors 公式+区间筛

    比赛的时候把公式扣出来了,,但是没有想到用筛法算公因子,,默默学习一下.. 题解:设n=p1^(c1)p2^{c2}...pm^{cm},n=p​1^​c​1*​​​​p​2​^c​2​​​​...p ...

  5. EFcore的 基础理解<二> shadow 特性

    接着上一篇.在MyEFTestContext 类中添加这个方法 protected override void OnModelCreating(ModelBuilder modelBuilder) { ...

  6. nginx触屏版跟PC的代理设置

    server { listen ; set $mobile_rewrite do_not_perform; if ( $http_user_agent ~* "(android|bb\d+| ...

  7. zepto学习(二)之tap事件以及tap事件点透处理

    前言 为什么通过touch可以触发click事件? touch事件的来源 PC网页上的大部分操作都是用鼠标的,即响应的是鼠标事件,包括mousedown.mouseup.mousemove和click ...

  8. wepy 开发小程序, 为什么设置pages路径的时候总是找不到 js 文件?

    1,路径先检查仔细了 2,别说话,重新run 3,可能是版本问题,重新搭工程

  9. mORMot学习笔记2-2种方式查询数据

    本例使用SqlServer 第一种方式结果放入Memo控件,,需要引用SynCommons, SynDB, SynOleDb; procedure TForm1.Button1Click(Sender ...

  10. jumpserver跳板机docker安装小小趟坑

    最近日常运维的时候发现每次登陆服务器都要打开终端目录连接对应的服务器,闲暇的时候还好,运维任务很重的时候才发现这样的玩法很傻,浪费时间且一点儿都跟不上潮流,然后打开githup开始搞起来.docker ...