20181015 考试记录&数论
小 M 的算式
【问题描述】
小 M 在做数学作业的时候遇到了一个有趣的问题:有一个长度为 n 的数字
串 S,小 M 需要在数字之间填入若干个“+”和恰好一个“=”,使其成为一个
合法的等式。如对于 S=“2349”,可以通过添加 2个“+”和 1 个“=”成为
“2+3+4=9”。
小 M 发现有些数字串是无法通过添加符号成为一个合法的等式的,她想知
道对于每一个给定的数字串 S,是否可以通过添加符号使之成为一个合法的等
式(允许前导 0)?
【输入】
第一行为数据组数 T,表示有 T组输入数据。
接下来 T行每行一个数字串 S。
【输出】
对于每组数据,若 S可以成为合法的等式,输出“Yes”,否则输出
“No”,以单行回车隔开。
【输入输出样例】
equation.in
4
2349
233233
122323
2344322322
equation.out
Yes
Yes
No
Yes
【输入输出样例解释】
2+3+4=9
233=233
2+34=4+3+2+2+3+22
【数据范围】
对于 50%的数据:1 ≤ T ≤ 3,1 ≤ n ≤ 4。
对于 100%的数据:1 ≤ T ≤ 5,1 ≤ n ≤ 10。
简单的搜索
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline long long read()
{
long long f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
char str[];
long long t,len,n1,n2;
long long cnt1[][],cnt2[][],s1,s2;
bool ff;
void dfs2(long long pos,long long ans,long long dq,long long dqs)
{
if(dqs+dq>s1) return;
if(ff) return;
if(pos==n2+)
{
s2=dqs+dq;
if(s1==s2)
ff=;
return;
}
cnt2[ans][++cnt2[ans][]]=str[pos]-'';
dq=dq*+str[pos]-'';
dfs2(pos+,ans,dq,dqs);
dq=(dq-(str[pos]-''))/;
cnt2[ans][]--; long long t=dq;
cnt2[ans+][++cnt2[ans+][]]=str[pos]-'';
dq=str[pos]-'';
dfs2(pos+,ans+,dq,dqs+t);
cnt2[ans+][]--;
dq=;
return;
}
void dfs1(long long pos,long long ans,long long dq,long long dqs)
{
if(ff) return;
if(pos==n1+)
{
s1=dqs+dq;
dfs2(n1+,,,);
return;
}
cnt1[ans][++cnt1[ans][]]=str[pos]-'';
dq=dq*+str[pos]-'';
dfs1(pos+,ans,dq,dqs);
cnt1[ans][]--;
dq=(dq-(str[pos]-''))/; long long t=dq;
cnt1[ans+][++cnt1[ans+][]]=str[pos]-'';
dq=str[pos]-'';
dfs1(pos+,ans+,dq,dqs+t);
cnt1[ans+][]--; dq=t;
return;
}
int main()
{
t=read();
while(t--)
{
ff=false;
scanf("%s",str+);
len=strlen(str+);
for(long long i=;i<len;i++)
{
n1=i,n2=len;
dfs1(,,,);
if(ff){cout<<"Yes"<<endl;break;}
}
if(!ff)cout<<"No"<<endl;
}
}
小R的调度
【问题描述】
小 R 是一名 OIer,她刚刚学习了逆序对的相关知识:对于一个长度为 n的
序列 A,其逆序对数定义为满足 i < j 且 A[i] > A[j]的(i, j)对数。
现在小 R 有一个长度为 n的 01序列 A,小 R每次可以交换 当前 A[i]与 A[j]
的值,并需要付出 c[i] + c[j]的代价。在若干轮(可以为空)交换后,小 R的得
分为最终 A序列的逆序对数减去她在交换中付出的代价之和。
小 R 想让最后的得分尽量大,你能帮帮她吗?
【输入】
第一行为一个正整数 n。
第二行为一个长度为 n的字符串,表示 01序列 A。
第三行为 n个整数 c[i],表示交换的代价参数。
【输出】
输出最大得分。
【输入输出样例】
inverse.in
6
101010
1 1 1 1 1 1
inverse.out
7
【样例解释】
交换 A[2]和 A[5],付出 1 + 1 = 2 的代价。
最终序列为 111000,逆序对数为 9,得分为 9 - 2 = 7。
【数据范围】
对于 100%的数据:1 ≤ n ≤ 2501,0 ≤ c[i] ≤ 100。
这是w神爷的题解:
注意到每次交换只有当两位置的元素不同才有意义,进一步分析可知序列的每个位置最多被交换一次,而每个从 0 换成 1 的位置与每个从 1 换成 0 的位置是一一对应的。
我们可以设计一个动态规划算法,设 f(i,j,k) 表示序列的前 i 个位置已经确定下来,前 i 个位置中有 j 个位置从 0 交换成了 1,有 k个位置从 1 交换成了 0。
转移时枚举第 i + 1 个位置有没有发生交换,根据初始 A 1 到 A i有多少个 1,以及 j、k 的值可以计算出第 i+1 个位置确定为 0 产生的逆序对贡献。
简称就是一个dp,可以想到转移为从0->1 与 1->0
然后就瞎搞
但是为什么可以dp呢
因为它不需要管后面发生了什么
最后维护的是差值
有加有减才能出来最后答案
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
int n,dp[][],cur,co,A[],inf=<<-;
char str[];
int main(){
n=read();
scanf("%s",str+);
for(int i=;i<=n;i++) A[i]=read();
memset(dp,-,sizeof(dp));
dp[][n]=;
for(int i=;i<=n;i++){
cur^=;
for(int j=;j<=*n;j++){
int ans=dp[cur^][j];
if(ans==-inf) continue;
if(str[i]==''){
dp[cur][j]=max(dp[cur][j],ans);
dp[cur][j-]=max(dp[cur][j-],ans+co-A[i]+j-n);
}
if(str[i]==''){
dp[cur][j]=max(dp[cur][j],ans+co+j-n);
dp[cur][j+]=max(dp[cur][j+],ans-A[i]);
}
}
if(str[i]=='') co++;
}
cout<<dp[cur][n];
}
小 C 的机器人
【问题描述】
小 C 的机器人工厂里有 m个机器人,标号为 1 到 m号。给定一棵 n 个节点
的有根树,根结点为 1号点,第 i个机器人初始在第 p[i]号点。树上每个节点有
一盏灯,初始灯都是灭着的。树上每条边的距离均为 1,且机器人每次移动的
距离均为 1。
你是小 C 工厂的技术顾问,需要写一个程序模拟 q次操作,操作共 3种类
型:
操作 1:1 l r x,表示将标号在 l 和 r之间的所有机器人移动到 x号节点。
操作 2:2 l r x,表示将标号在 l 和 r之间的所有机器人向根结点移动 x步。
若移动步数超过机器人到根节点的距离,则机器人会停在根节点。
操作 3:3 x,表示将 x号机器人当前所在节点的灯的亮灭状态取反,并查
询当前所在节点到其子树内所有亮着灯的节点的距离之和。
【输入】
第一行为两个正整数 n,m。
第二行至第 n行每行两个正整数 u、v,表示一条从 u到 v 的树边。
第 n+1 行为 m 个正整数,第 i 个正整数表示 p[i]。
第 n+2 行为一个正整数 q。
接下来 q行表示 q 个操作,具体格式见样例。
【输出】
输出若干行,第 i行的整数表示第 i 个操作 3的答案。
【输入输出样例】
robot.in
5 4
1 2
1 3
3 4
3 5
1 1 1 1
8
1 2 2 4
1 3 3 5
3 3
3 2
2 2 2 1
3 2
3 3
3 2
robot.out
0
0
2
0
1
【数据范围】
对于 20%的数据满足:1 ≤ n、m、q ≤ 10。
另有 20%的数据满足:1 ≤ n ≤ 50。
另有 20%的数据满足:1 ≤ m ≤ 20。
对于 100%的数据满足:1 ≤ n、m、q ≤ 152501,1 ≤ u、v、p[i]、x ≤ n,1 ≤ l≤ r ≤ m
毒瘤题目,到最后也没有写完,还算错复杂度
将这个问题分解,不难想到其实就是两个子问题
机器人的移动与子树距离
第二个线段树用一下树链剖分的思想,十分简单
想一下dfs在树上的时间戳
若到达第i点的时间戳为k,并且它的子树大小为s,所以它在线段树中所
所以建两个线段树去维护,lca去加速往上跳
悲催的调试:第二个线段树写错,第一个线段树写错,lca写错
最后就完了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return ans*f;
} int p[],head[],tt[];
int cnt,deep[],fa[][],pd;
int n,m,pig,size[],seg[];
int rev[*],ans[*],q; struct node{
int u,v,nex;
}x[]; void dfs(int f,int fath)
{
size[f]=;
tt[f]=++pig;
seg[pig]=f;
deep[f]=deep[fath]+;
fa[f][]=fath;
for(int i=;(<<i)<=deep[f];i++) fa[f][i]=fa[fa[f][i-]][i-];
for(int i=head[f];i!=-;i=x[i].nex)
{
if(x[i].v==fath) continue;
dfs(x[i].v,f);
size[f]+=size[x[i].v];
}
return;
} int jump(int u,int h)
{
for(int i=;i>=;i--)
if(h-(<<i)>=) u=fa[u][i],h-=(<<i);
if(u==) return ;
return u;
} void add(int u,int v)
{
x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
} void build_seg(int k,int l,int r)
{
if(l==r){
rev[k]=p[l];return;
}
int mid=l+r>>;
build_seg(k<<,l,mid);
build_seg(k<<|,mid+,r);
return;
}
void pushdown_seg(int k,int l,int r)
{
if(rev[k]!=)
{
ans[k<<]=ans[k<<|]=;
rev[k<<]=rev[k<<|]=rev[k];
rev[k]=;
}
if(ans[k]!=)
{
ans[k<<]+=ans[k];
ans[k<<|]+=ans[k];
ans[k]=;
}
return;
}
void change_seg(int k,int l,int r,int x,int y,int s)
{ if(x<=l&&r<=y){
if(pd==){
rev[k]=s;
ans[k]=;
}
else if(pd==){
ans[k]+=s;
}
return;
}
pushdown_seg(k,l,r);
int mid=l+r>>;
if(x<=mid) change_seg(k<<,l,mid,x,y,s);
if(mid<y) change_seg(k<<|,mid+,r,x,y,s);
return;
} int query_seg(int k,int l,int r,int x,int y)
{
if(x==l&&r==y){return jump(rev[k],ans[k]);}
pushdown_seg(k,l,r);
int mid=l+r>>;
if(x<=mid) return query_seg(k<<,l,mid,x,y);
if(mid<y) return query_seg(k<<|,mid+,r,x,y);
}
int sum[*];
int flag[*];
void change(int k,int l,int r,int x,int y)
{
if(l==x&&r==y){
if(flag[k]==) {
flag[k]=;
sum[k]=;
}else if(flag[k]==){
flag[k]=;
sum[k]=deep[seg[l]]-;
} return;
}
int mid=l+r>>;
if(x<=mid) change(k<<,l,mid,x,y);
if(mid<y) change(k<<|,mid+,r,x,y);
sum[k]=sum[k<<|]+sum[k<<];
flag[k]=flag[k<<]+flag[k<<|];
return;
}
int ff; int query(int k,int l,int r,int x,int y)
{ if(x<=l&&r<=y){
ff+=flag[k];
return sum[k];
}
int mid=l+r>>,st=;
if(x<=mid) st+=query(k<<,l,mid,x,y);
if(mid<y) st+=query(k<<|,mid+,r,x,y);
return st;
} int main()
{
memset(head,-,sizeof(head));
n=read(),m=read();
for(int i=;i<n;i++)
{
int u=read(),v=read();
add(u,v),add(v,u);
}
dfs(,);
for(int i=;i<=m;i++) p[i]=read();
build_seg(,,m);
q=read();
while(q--)
{
pd=read();
if(pd==||pd==){
int l=read(),r=read(),xx=read();
change_seg(,,m,l,r,xx);
}
if(pd==)
{
int st=read();
int pos=query_seg(,,m,st,st);
ff=;
int kk=query(,,n,tt[pos]+,tt[pos]+size[pos]-);
change(,,n,tt[pos],tt[pos]);
printf("%d\n",kk-ff*(deep[pos]-));
}
}
}
20181015 考试记录&数论的更多相关文章
- 【考试记录】4.8 Table ( 数论数学 --组合数 & 杨辉三角)
陆陆续续的开始考很多的试,也会更新这些题目记录下来,免得做完了之后毫无印象,就这么水过去了(以前的考试都是如此,哎……) Table (T1) : 样例: 出于对数学题本能的恐惧考场上放弃了此题专攻T ...
- [总结] NOIP 前的考试记录
sb博主又犯sb错误了! 他觉得以往模拟赛因为犯sb错误扔的分足足有1k分了! 于是他想记录一下自己犯的sb错误看看自己到底有多sb! 嗯就从今天开始吧 2018.9.28 1. 二分边界写错.骚什么 ...
- 20181022 考试记录&高级数据结构
题目 W神爷的题解 高级数据结构 T1: 其实是一道easy题,$O(n^3log n)$ 也是能卡过去的,本着要的70分的心态,最后尽然A了. 如果是正解则是$O(n^3)$,当确定你要选择的列时, ...
- 【考试记录】Educational Codeforces Round 59 (Rated for Div. 2)
本来准备划水,结果被垃圾题艹翻了…… T2题意: 定义一个数$x$的数字根$S(x)$为:将其各位数字相加得到一个新数,再将新数的数字和相加直到得到一个个位数,就是该数的数字根. 例如:$S(38)= ...
- 【考试记录】4.8 Path (网络流 —— 劲题)
手抄代码 + 学习指针 + 冥思苦想一晚上终于——在一瞬间开窍了.果然题目都是这样:突破了一个点,一切都是柳暗花明. 题面描述: 样例: 这道题目,首先注意到给定的边的性质:这些边在平面上构成了一棵树 ...
- 【考试记录】2018 山东省队集训第一轮D4(雾)
T1题意: 给你一个$n\times m$的矩阵$B$,求它能由最少多少个形如两个向量之积$(n\times 1)\times(1\times m)$的矩阵相加得到. 题解: 考虑上界,最多需要$mi ...
- CCF考试
第八次CCF考试记录 代码还不知道对不对,过两天出成绩. 成绩出来了,310分. 100+100+100+10+0: 考试13:27开始,17:30结束,提交第4题后不再答题,只是检查前四题的代码 第 ...
- PHPEMS在线模拟考试系统 v4.2
官网地址 :http://www.phpems.net/ 下载地址 : http://www.phpems.net/index.php?content-app-content&contenti ...
- 基于java开发jsp+ssm+mysql实现的在线考试系统 源码下载
实现的关于在线考试的功能有:用户前台:用户注册登录.查看考试信息.进行考试.查看考试成绩.查看历史考试记录.回顾已考试卷.修改密码.修改个人信息等,后台管理功能(脚手架功能不在这里列出),科目专业管理 ...
随机推荐
- 前台时间格式 2019-03-09T16:00:00.000Z
问题描述: 本想在前台把字符串格式的日期(2019-03-09)转换成日期格式(2019-03-09 00:00:00),但当把这个参数传到后台去后却变成了2019-03-08T16:00:00.00 ...
- jmeter的脚本增强之参数化
jmeter作为一款开源的测试工具,功能广泛,深受测试同胞们的喜爱,这次来讲讲关于如何参数化及其方式.那为什么要进行一个参数化呢,如做压测时,要有大量的数据来模拟用户的真实场景,像登录页面操作,系统是 ...
- 第八模块:算法&设计模式、企业应用 第1章 常用算法&设计模式学习
第八模块:算法&设计模式.企业应用 第1章 常用算法&设计模式学习
- JS原型链与继承别再被问倒了
原文:详解JS原型链与继承 摘自JavaScript高级程序设计: 继承是OO语言中的一个最为人津津乐道的概念.许多OO语言都支持两种继承方式: 接口继承 和 实现继承 .接口继承只继承方法签名,而实 ...
- Java进阶知识点:更优雅地关闭资源 - try-with-resource
一.背景 我们知道,在Java编程过程中,如果打开了外部资源(文件.数据库连接.网络连接等),我们必须在这些外部资源使用完毕后,手动关闭它们.因为外部资源不由JVM管理,无法享用JVM的垃圾回收机制, ...
- Java三种编译方式
Java程序代码需要编译后才能在虚拟机中运行,编译涉及到非常多的知识层面:编译原理.语言规范.虚拟机规范.本地机器码优化等:了解编译过程有利于了解整个Java运行机制,不仅可以使得我们编写出更优秀的代 ...
- fp-growth树创建代码及详细注释
事务集过滤重排: #FP树节点结构 class treeNode: def __init__(self,nameValue,numOccur,parentNode): self.name=nameVa ...
- oraclize预言机资料
oraclize预言机资料 智能合约如何可信的与外部世界交互: https://blog.csdn.net/sportshark/article/details/77477842 国外一篇讲得很详细的 ...
- 第四课——MFC应用程序框架
一.MFC应用程序类型 上篇文章的彩蛋:可通过使用MFC应用程序向导(MFC AppWizard)的功能来创建所需要的应用程序,这意味着不需要输入任何代码.MFC除了应用程序向导,还对应用程序项目有着 ...
- 初涉算法——STL初步
一.头文件<algorithm> ①sort函数 sort使用数组元素默认的大小比较运算符进行排序,只有在需要按照特殊依据进行排序时才需要传入额外的比较函数: sort可以给任意对象排序( ...