2018青岛(重温经典)

  • 导语
  • 涉及的知识点
  • 题目
    • C
    • D
    • E
    • F
    • J
    • M
  • 参考文献

导语

难度不高的一次训练,但是还是很考思维的

涉及的知识点

思维,构造,平面几何,搜索

链接:The 2018 ACM-ICPC Asia Qingdao Regional Contest

题目

C

题目大意:给出两个01串 s , t s,t s,t,长度不超过106,规定一种操作,每次操作可以将区间 [ l , r ] [l,r] [l,r]内的所有元素取反,现在想要将 s s s经过两次操作之后变成 t t t,询问有多少种方案可以满足(将两次操作 [ l 1 , r 1 ] , [ l 2 , r 2 ] [l_1,r_1],[l_2,r_2] [l1​,r1​],[l2​,r2​]构成一个四元组 ( l 1 , r 1 , l 2 , r 2 ) (l_1,r_1,l_2,r_2) (l1​,r1​,l2​,r2​),两种方案不同只要四元组有一个元素不同即可)

思路:如图,可以将 s s s和 t t t的关系分成三种情况,红色部分为不同区间

  1. s s s与 t t t只有一个连续区间不同
    在这种情况下,如图,可以第一次将左边的黄色区间与红色区间整体取反,之后再对黄色区间单独取反,这样得出来的结果合法,同理,黄色区间也可以在右边,整体方案数为2×红区间左端点到左端点长度+2×红区间右端点到右端点长度(×2是因为可以调换顺序),还有别的方案就是将红色区间分成左右两块分别取反即可
  2. s s s与 t t t有两个不相交的连续区间不同
    在这种情况下,显然只有三种组合(不考虑顺序): ( A , B ) , ( A C , C B ) , ( A C B , C ) (A,B),(AC,CB),(ACB,C) (A,B),(AC,CB),(ACB,C),答案固定为6种
  3. s s s与 t t t至少有三个不相交的连续区间不同
    这种情况下找不到只用两次操作就能完成转换的方案,方案数为0

代码

#include <bits/stdc++.h>
#define int long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=1e6+10;
int T,n,l[4],r[4],cntl,cntr;
char s[maxn],t[maxn];
signed main() {scanf("%lld",&T);while(T--) {bool flag=0;scanf("%lld",&n);scanf("%s%s",s+1,t+1);//扫描初始和终了字符串cntl=cntr=0;int low=0,high=0;//记录当前块的左右端点for(int i=1; i<=n; i++) {//寻找不同块if(s[i]!=t[i]) {if(low) {if(i!=n)continue;r[cntr++]=i;//记录每个块右端点continue;}low=high=i,l[cntl++]=i;//记录左端点}if(s[i]==t[i]) {if(!high)continue;high=i-1,r[cntr++]=i;low=high=0;}if(cntr==3||cntl==3) {//超过2块无解flag=1;break;}}if(flag) {printf("0\n");continue;}if(cntl==2)printf("6\n");else if(cntl==1) {//单独一个块直接计算int res=0;res+=2*(r[0]-l[0]+l[0]-1+n-r[0]);printf("%lld\n",res);} elseprintf("%lld\n",(n+1)*n/2);}return 0;
}

D

题目大意:对于给定的两个数 A , B A,B A,B,假设 A = a 1 a 2 … a n , B = b 1 b 2 … b m A=a_1a_2\dots a_n,B=b_1b_2\dots b_m A=a1​a2​…an​,B=b1​b2​…bm​, a i , b i a_i,b_i ai​,bi​分别为 A , B A,B A,B对应位上的数(十进制),定义一种运算 A ⊗ B = ∑ i = 1 n ∑ j = 1 m a i b j = a 1 b 1 + a 1 + ⋯ + a 1 b m + a 2 b 1 + … A ⊗B=\sum_{i=1}^{n}\sum_{j=1}^{m}a_ib_j=a_1b_1+a_1+\dots+a_1b_m+a_2b_1+\dots A⊗B=∑i=1n​∑j=1m​ai​bj​=a1​b1​+a1​+⋯+a1​bm​+a2​b1​+…,现在给出运算结果,求出 A , B A,B A,B,如果答案有多个,以最小的 A A A为基准,如果仍有多个,以最小的 B B B为基准

思路:最后的运算结果相当于多个结果作字符串的拼接,对于每个结果来说,其因数对不超过两个,所以可以暴力尝试1 ~ 9构造并搜索,对于每个结果,如果结果为两位数,则结果的十位小于两因数的任意一个,结果为一位数,乘积大于两因数任意一个

在搜索时,根据给定的运算结果,将结构对应为与当前位进行比较,如果结果小于当前枚举数字,取结果两位,否则取一位

由于题目需要求最小的A,那么首先构造A,将A的第一位从1 ~ 9进行尝试构造,然后通过构造出来的A反推B,具体见代码

PS:参考博客的代码写的真是精妙

代码

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=2e5+5;
int T,n,m,a[maxn],b[maxn];
char c[maxn];
bool GetB() {int len=strlen(c),pos=0;for(int i=0; i<m; i++) {if(pos==len)return 0;//字符串不够用,不合法int x=c[pos++]-'0';//获得对应数字if(pos<len&&x&&x<a[0])x=x*10+c[pos++]-'0';//如果字符串够用,这一位不为0,数字小于a[0],就需要多拿一位if(x%a[0]||x/a[0]>9)return 0;//如果不能整除或者商为两位数b[i]=x/a[0];//构造b[i]}for(int i=1; i<n; i++)for(int j=0; j<m; j++) {if(pos==len)return 0;int x=c[pos++]-'0';//获得对应数字if(pos<len&&x&&x<b[j])x=x*10+c[pos++]-'0';//如果字符串够用,这一位不为0,数字小于a[0],就需要多拿一位if(x&&(b[j]==0||(j&&a[i]==0)))return 0;//如果有结果但是b的对应位为0或者a的对应位为0(j代表已经计算过,根据0~j-1推出a[i]==0)if(x==0) {if(j&&a[i]&&b[j])return 0;//结果有0并且a[i]已经算过,b的对应为有值if(!j)a[i]=0;//如果第一次算,结果为0,则a[i]为0} else {if (x%b[j]||j&&x/b[j]!=a[i]||x/b[j]>9) return 0;//如果不能整除或者商为两位数a[i]=x/b[j];}}return pos==len;
}
bool Judge(int x) {for(int i=1; i<=9; i++)if(x%i==0) {a[0]=i;if(GetB())return 1;}return 0;
}
bool solve() {int x=c[0]-'0';if(Judge(x))return 1;x=x*10+c[1]-'0';if(Judge(x))return 1;return 0;
}
int main() {scanf("%d",&T);while(T--) {scanf("%d%d%s",&n,&m,&c);if(solve()) {for(int i=0; i<n; i++)printf("%d",a[i]);putchar(' ');for(int i=0; i<m; i++)printf("%d",b[i]);putchar('\n');} else printf("Impossible\n");}return 0;
}

E

题目大意:n个植物,坐标为1 ~ n,给出每个植物浇一次水之后的增长量,现从i=0开始移动,可以到达数轴的任意地方,每次移动一步,最多只能移动m步,每次移动之后,如果当前下标有植物,则必须浇水,现在求m次之后所有植物的最小高度的最大值是多少

思路:如果用模拟的思路考虑,就要考虑怎么走,走多少步,走当前步是否会影响之后的植物,是非常复杂的,正难则反,不如从答案开始考虑,直接二分最小高度的最大值,并尝试构造出这样的值,从0开始前进,每一次将当前植物浇到目标值,如果浇一次不够,那么就向前走一步再走回来,直到植物的高度满足目标值,依次类推,查看步数是否足够构造,详见代码

代码

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define int long long
using namespace std;
const int maxn=1e5+10;
int T,n,m,a[maxn];
bool Judge(int goal) {int now=0,last=0,step=m;for(int i=1; i<n; i++) {//这里没有遍历到最后一个,因为最后一个没有后置now=a[i]*(last+1);//last为为了将a[i-1]达到goal,在i-1反复横跳的浇水次数step--;//走到了iif(now<goal) {//如果没达到goallast=(goal-now+a[i]-1)/a[i];//需要反复横跳的次数step-=(last<<1);//一次反复横跳对应两步if(step<0)return 0;//步数不够} else last=0;}if(a[n]*last<goal) {//特判最后一个step--;//走到了nlast=(goal-a[n]*last-1)/a[n];//res=goal-a[n]*y-a[n],还需要的步数//(res+a[n]-1)/a[n],反复横跳step-=(last<<1);}return step>=0;//判断步数是否足够
}
signed main() {ios::sync_with_stdio(0);cin.tie(0);cin >>T;while(T--) {cin >>n>>m;int mx=0,res=0;for(int i=1; i<=n; i++) {cin >>a[i];mx=max(mx,a[i]);//获得最大值作为边界}if(m<n) {cout <<0<<endl;continue;}int l=0,r=mx*m+1;//上界和下界while(l<=r) {//二分int mid=(l+r)>>1;if(Judge(mid)) {res=mid;l=mid+1;} elser=mid-1;}cout <<res<<endl;}return 0;
}

F

题目大意:n个骑士,编号1 ~ n,骑士间需要决斗,每轮比赛有多场决斗,比赛的规则如下:

  1. 比赛一个有k轮,每一轮包括许多决斗,决斗只发生在两个骑士之间
  2. 每个骑士在每场比赛中必须参加一次决斗
  3. 对每一对决斗的骑士来说,两人之间在所有的比赛过程中最多只有一次决斗
  4. 假设 1 ≤ i , j ≤ k , i ≠ j , 1 ≤ a , b , c , d ≤ n 1\le i,j\le k,i≠j,1\le a,b,c,d\le n 1≤i,j≤k,i​=j,1≤a,b,c,d≤n(a,b,c,d为四个正整数),如果 a a a在第 i i i轮和 b b b决斗过, c c c在第 i i i轮和 d d d决斗过,并且 a a a和 c c c在第 j j j轮决斗了,那么 b b b必须在第 j j j轮与 d d d决斗

求出一个可行的分配方案,不存在则输出对应字符串

思路:这道题,第四个条件非常关键,必须仔细琢磨才能知道真正的含义,显然,如果骑士的个数是奇数,无可行方案,但是是否所有的偶数都可行?
假设有 2 k n 2^kn 2kn个骑士,分别讨论 n n n为1和 n n n不为1(n为奇数)的情况

  1. n n n不为1,那么 n n n= 2 p + 1 2p+1 2p+1,以n=3为例,根据比赛规则,在第一局匹配有如下的情况

    那么第二局就有两种匹配方案,如图所示,可以看到,不管是哪种匹配,都会有一对不能匹配的编号,而当 n n n为更大的奇数时,结果无非是 n = 3 n=3 n=3的重复与延伸,也同样适用这一规律

  2. n n n为1,则相对于奇数情况,等价于有许多个4个一组的编号可以互相匹配,总匹配局数大于2(只有两个人除外)

因此,对于输入的数据,判断是否为2的整数次幂,如果是则根据对应k求解,如果不是则进一步判断奇数的情况

代码

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define int long long
using namespace std;
const int maxn=1e3+50;
int T,n,k,res[maxn][maxn];
void Pre(int x,int y,int n,int v) {//预处理1024内的表if(n==1) {res[x][y]=v;return ;}n/=2;Pre(x,y,n,v);//处理左边Pre(x,y+n,n,v+n);//处理右边for(int i=1; i<=n; i++)//对角赋值for(int j=1; j<=n; j++) {res[x-1+i+n][y-1+j]=res[x-1+i][y-1+j+n];res[x-1+i+n][y-1+j+n]=res[x-1+i][y-1+j];}
}
signed main() {ios::sync_with_stdio(0);cin.tie(0);cin >>T;Pre(1,1,1024,1);while(T--) {cin >>n>>k;if(k>=(n&-n))//最多行cout <<"Impossible\n";else {for(int i=2; i<=k+1; i++) {cout <<res[i][1];for(int j=2; j<=n; j++)cout <<" "<<res[i][j];cout <<endl;}}}return 0;
}

J

题目大意:有n本书,每本书有价格 p ( 0 ≤ p ≤ 1 0 9 ) p(0\le p\le 10^9) p(0≤p≤109),现在想要购买m本书,假设初始钱数为 w w w,购买策略如下:对于第 i i i本书,如果所持有的钱数大于等于其价格,购买且持有钱数对应减少,否则跳过,求出最多能带的初始钱数能使得恰好购买m本书

思路:首先,如果m>n,无解,m==n,钱数可以是无穷,m<n,需要判断价格为0的书有多少,这些必然会被买下,假设数量为 k k k,那么剩下的 m − k m-k m−k本书就直接购买前 m − k m-k m−k个价值不为0的书即可,因为这样的持有钱最大,之后结果再加上后 n − m n-m n−m本书中的最小值-1即可

代码

#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int N=1e6+6;
ll a[N];
void solve() {int n,m;scanf("%d%d",&n,&m);int cnt0=0;ll minx=INF;for(int i = 1; i <= n; i++) {scanf("%lld",a+i);if(a[i]==0) {cnt0++;} else {minx=min(minx,a[i]);}}if(n==m) {printf("Richman\n");return;}ll res = 0;if(cnt0>m) {printf("Impossible\n");} else if(cnt0 == m) {printf("%lld\n",minx-1);} else {minx=INF;m-=cnt0;int i = 1;for(; i <= n&&m; i++) {if(a[i]) {res+=a[i];m--;}}for(; i <= n; i++) {if(a[i]) {minx=min(minx,a[i]);}}res+=(minx-1);printf("%lld\n",res);}
}
int main() {int t;scanf("%d",&t);while(t--)solve();return 0;
}

M

题目大意:略

思路:很容易发现规律,经过第一次运算之后,原数字必然会变成两位数,再经过有限次运算后,最后的结果就会变成01的循环,根据运算次数输出对应的答案即可

代码

#include <bitsdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
const int mod = 1e9+7;
int a[10]= {1,0,0,0,1,0,1,0,2,1};
int cal(int x) {int res=0;if(x==0)return 1;while(x>0) {int yu=x%10;x/=10;res+=a[yu];}return res;
}
void solve() {int x,k;scanf("%d%d",&x,&k);int temp1=x;for(int i=1; i<=k; i++) {temp1=cal(temp1);if(temp1==0) {if((k-i)%2==0)temp1=0;elsetemp1=1;break;} else if(temp1==1) {if((k-i)%2==0)temp1=1;elsetemp1=0;break;}}printf("%d\n",temp1);
}int main() {int t = 1;scanf("%d",&t);while(t--) {solve();}return 0;
}

参考文献

  1. D - Magic Multiplication(The 2018 ACM-ICPC Asia Qingdao Regional Contest)(找规律+构造)
  2. Plants vs. Zombies(二分)
  3. 2018青岛ICPC && ZOJ 4063: Tournament(构造)

2018青岛(重温经典)相关推荐

  1. 电影AI修复,让重温经典有了新的可能

    摘要:有没有一种呈现,不以追求商业为第一目的,不用花大价钱,不用翻拍,没有画蛇添足,低成本的可共赏的让经典更清晰? 本文分享自华为云社区<除了重映和翻拍,重温经典的第三种可能>,原文作者: ...

  2. 2017南宁(重温经典)

    2017南宁(重温经典) 导语 涉及的知识点 题目 H I M L 参考文献 导语 这场打的还可以,也学到了二分图的更简单的建图和匹配实现,虽然以前看过,但没有着重关注,这次直接整理了 涉及的知识点 ...

  3. 2020icpc上海(重温经典)

    2020icpc上海(重温经典) 导语 涉及的知识点 题目 B D G H I M 参考文献 导语 涉及的知识点 思维,几何,搜索 链接:第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(上海 ...

  4. html程序国庆节祝福,2018年国庆节经典祝福语

    2018年国庆节经典祝福语 1.任时光匆匆,岁月流逝.永不腿色的是祝福;永不改变的是友情.我深深的祝福你开心快乐每一天.愿这短短的话语给你带来国庆的快乐 2.祝福是美丽的鲜花,散发着阵阵清香;祝福是淡 ...

  5. 2021上海站(重温经典)

    2021上海站(重温经典) 导语 涉及的知识点 题目 D E G I K 参考文献 导语 拿来练手的,好长时间没弄了,生疏了不少,思维和分析需要再加强 涉及的知识点 思维,数学,背包DP,树形DP,K ...

  6. 重温经典:简读光干涉、衍射原理

    如果您不是光学专业的,或者是文科生,那么您想到光的干涉和衍射第一反应应该是很多公式对不对?头好大是不是?好,那么今天我们就不用一个公式来重新解读光的干涉和衍射. 光,也叫电磁波,他的表现形式我们通常用 ...

  7. 让我们重温经典---TVB十大感人爱情故事

    让我们重温经典---TVB十大感人爱情故事 此主题相关图片如下: 1.<上海滩>:当许文强中枪后,丁力抱着许文强,许文强临死前说:"你知道我要去哪儿么?我要去找程程." ...

  8. 让电影票房飞一会儿,五一换个姿势重温经典

    距离五一小长假,还有不到20个小时!和我们一起迎接五一的,还有14部影片,号称史上最挤五一档!小编没有说错,"最挤"而不是"最强". 五一电影预售票房已经出炉, ...

  9. linux win95模拟,【重温经典】Windows 95 模拟软件--记忆中的扫雷和纸牌

    软件平台:Windows/Mac os/Linux 今天给大家分享一个东西,虽然没啥卵用... 简单介绍 聊天软件 Slack 的开发者 Felix Rieseberg 把 Windows 95 变成 ...

最新文章

  1. java 类的执行顺序_java类加载的顺序
  2. Windows PE入门基础知识:Windows PE的作用、命名规则、启动方式、启动原理
  3. python turtle画彩虹-Python turtle 绘制彩色螺旋线
  4. android应用的构成组件
  5. 一个有趣的算法问题:如何定义一个分数类
  6. [TJOI2017]城市(未解决)
  7. 大数据和后端学习知识体系思维导图
  8. 百旺智能编码_【百旺】票字版开票软件操作指南已为您备好,请查阅!
  9. lightoj 1382 - The Queue(树形dp)
  10. “阿里灵杰”问天引擎电商搜索算法赛 - 数据说明2022
  11. 基于Bootstrap的后台通用模板
  12. 硬笔行书字帖3500常用字_练字的字帖怎么选择?(硬笔)
  13. Eclipse安装中文简体语言包(官方下载安装教程)
  14. 单片机原理及应用试卷c51语言,51单片机原理及应用期末考试试题汇总
  15. 学习笔记(16):程序员的数学:微积分-常用导数(一):最常用到的技巧
  16. 我的硬件工程师成长之路
  17. 计算机硬盘最小容量是多少,通常计算机的存储容量是多少?
  18. Linux下设置网卡速率 降低网卡速度
  19. Lunix磁盘与文件系统管理
  20. C#实现毫秒级计时器

热门文章

  1. Haskell99题答案
  2. 神策营销云平台化应用实践
  3. 法国龙凤胎洗澡睡着 紧抱对方相互依偎(图)
  4. 最常有用的英语口语900句
  5. 分享一下自己常用的电脑快捷键
  6. 1.1-Selenium是什么?Selenium自动化测试介绍
  7. 爱聚云店宝V1.2.6上线,全面提升用户体验
  8. gmock入门(转)
  9. 剑指Offer —— 面试题(十二)
  10. 《聊天的55条公式》笔录