A.MinMax swap

我们假定两个序列中最大值为MAX,则无论如何交换,A或B序列中必有一个序列最大值为MAX。

则答案固定为MAX*max(A) 或 MAX*max(B).最小化max(A)或max(B)即可。我的代码是最小化max(B).

代码:

​
​
#include<iostream>
#include<algorithm>
using namespace std;
int main(void)
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int t;cin>>t;while(t--){int N;cin>>N;int a[200],b[200];for(int i=0;i<N;i++){cin>>a[i];}for(int i=0;i<N;i++){cin>>b[i];}for(int i=0;i<N;i++){if(a[i]<b[i])//将较大值置入A{swap(a[i],b[i]);}}sort(a,a+N);//排序,默认从小到大sort(b,b+N);cout<<a[N-1]*b[N-1]<<endl;//输出答案}return 0;
}​​

B.GCD VS LCM

一道简单的构造,由于lcm较难固定,所以我们不妨令c=1,d=1.则lcm(c,d)=1.而lcm(c,d)=gcd(a,b)

不妨令a=1.则gcd(a,b)=1.又a+b+c+d=n.则b=n-3.此即为本题特判。

当然,构造题往往有多解,能AC的构造就是好的构造。

代码:

#include<iostream>
#include<algorithm>
#include<string>
#define endl "\n"
using namespace std;
void solve(void)
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int t;cin>>t;while(t--){int n;cin>>n;cout<<1<<" "<<n-3<<" "<<1<<" "<<1<<endl;}
}
int main(void)
{solve();return 0;
}

C.Parentheses Balance

一道经典的问题,判断括号序列是否合法。我采用栈来实现括号表达式匹配。

push与pop是压栈与出栈操作的专用术语。

从左往右扫描字符串,如果是左括号则压栈,右括号则出栈。最后判断栈内是否为空即可。如果不匹配则直接跳出并判断非法。

代码:

//利用栈进行括号表达式匹配
#include<iostream>
#include<algorithm>
#include<stack>
#include<string>
#define endl "\n"
using namespace std;
int main(void)
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int T;cin>>T;cin.get();while(T--){string s;getline(cin,s);stack<char> st;bool vis=true;//初始默认合法for(int i=0;i<s.length();i++){if(s[i]=='['||s[i]=='('){st.push(s[i]);//压栈}else if(s[i]==']'||s[i]==')'){if(st.empty())//如果栈为空且遇到右括号{vis=false;break;}if(s[i]==')'){if(st.top()=='(')//匹配则出栈{st.pop();}else{break;}}else{if(st.top()=='['){st.pop();}else{break;}}}}if(!st.empty())//如果栈内非空{vis=false;}if(vis){cout<<"Yes"<<endl;}else{cout<<"No"<<endl;}return 0;
}

D.Subtract Operation

二分,思维。

假设序列为 a1,a2,...an. 第一次操作删去a1,则序列变为 a2-a1,a3-a1,...,an-a1.

第二次操作删去a2,则 序列变为 a3-a2,a4-a2,...,an-a2.

...

第n-1次操作删去aj 序列变为 aj-ai

则原问题转化为序列中是否存在 aj-ai=k (i != j)

如果暴力查找会超时,这里我们采取二分的思路。

首先对原序列排序。

如若 上式成立,则存在 aj 有 ai=aj-k 。我们从左往右固定 aj 二分查找 是否存在这样的 ai 即可

代码:

#include<iostream>
#include<algorithm>
#include<string>
#include<cmath>
#define endl "\n"
using namespace std;
using ll = long long;
const int maxn = 2e5 + 10;
int arr[maxn];
void solve(void)
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int t;cin>>t;while(t--){int n,k,sum;cin>>n>>k;for(int i=0;i<n;i++){cin>>arr[i];}bool vis=false;sort(arr,arr+n);//排序for(int j=1;j<n;j++){int i=lower_bound(arr,arr+j,arr[j]-k)-arr;//二分查找大于等于arr[j]-k的元素下标while(i<j){if(arr[j]-arr[i]==k)//找到则合法{vis=true;goto out;}else if(arr[j]-arr[i]<k)//小于k则移动arr[j]继续寻找{break;}i++;}}out:if(vis){cout<<"YES"<<endl;}else{cout<<"NO"<<endl;}}
}
int main(void)
{solve();return 0;
}

E.Eating Candies

前缀和,后缀和,二分或双指针。

对于每一个序列,将其前缀和与后缀和序列分别计算出来,固定前缀序列,查找后缀序列中相等元素的下标,满足要求则更新答案。

代码:

#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#define endl "\n"
using namespace std;
const int maxn = 2e5 + 10;
int dis[maxn];//糖果重量
int pre_sum[maxn];//前缀和
int post_sum[maxn];//后缀和
void solve(void)
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int t;cin>>t;while(t--){int n;cin>>n;for(int i=0;i<n;i++){cin>>dis[i];}pre_sum[0]=dis[0];post_sum[0]=dis[n-1];for(int i=1;i<n;i++)//递推计算前缀和与后缀和{pre_sum[i]=pre_sum[i-1]+dis[i];post_sum[i]=post_sum[i-1]+dis[n-i-1];}int ans=0;for(int i=0;i<n;i++){int l=lower_bound(post_sum,post_sum+n,pre_sum[i])-post_sum;//寻找下标while(l<=n-i-2)//下标合法{if(post_sum[l]>pre_sum[i])//如果l时后缀和大于前缀和则退出{break;}else if(post_sum[l]==pre_sum[i]&&pre_sum[i]!=0)//等于且不为0则更新答案{ans=max((l+i+2),ans);//答案取较大值}l++;}}cout<<ans<<endl;}
}
int main(void)
{solve();return 0;
}

F.2-Letter Strings

字符串处理,容斥原理。

对于每个字符串,将其按首尾字符分类存放到二维数组中。如若两字符串符合要求,则首尾字符必有且仅有一个相同。假设四个字符串第二字符两两不同,且数量分别为a,b,c,d。

则对于第一种字符串来说,可以组成a*(b+c+d) 种二元组。类似的,b字符串组成b*(a+c+d)种二元组。同理,对尾字符相同的字符串按同样的方法统计。

具体来说,如若F[i]表示首字符为‘a’+i 的字符串总数量,S[i]表示第二字符为'a'+i的字符串总数量。

dict[i][j]表示首字符为'a'+i,第二字符为'a'+j的字符串数量。则dict[i][j]对答案的贡献为

dict[i][j]*(F[i]-dict[i][j])+dict[i][j]*(S[j]-dict[i][j]);

则每一次我们只需扫描dict数组,就可以在26*26次乘法后找出答案。

由于每个字符串被统计了两次,所以答案要除以二。

注意该题在计算贡献时会爆int,要用long long.

代码:

#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#define endl "\n"
using namespace std;
using ll = long long;
const int maxn = 1e5 + 10;
string dict[maxn];
void solve(void)
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int t;cin>>t;while(t--){ll D[26][26]={0};llF[26]={0};ll S[26]={0};int n;cin>>n;for(int i=0;i<n;i++)//字符串分类{cin>>dict[i];D[dict[i][0]-'a'][dict[i][1]-'a']++;F[dict[i][0]-'a']++;S[dict[i][1]-'a']++;}ll sum=0;for(int i=0;i<26;i++){for(int j=0;j<26;j++)//计算贡献{sum+=(D[i][j]*(F[i]-D[i][j]));sum+=(D[i][j])*(S[j]-D[i][j]);}}cout<<sum/2<<endl;}
}
int main(void)
{solve();return 0;
}

G.Play on Words

经典图论题,将每个单词首尾字母作为结点,则单词变为从一个结点指向另一个结点的有向边。只需判断图中是否存在欧拉道路即可。

有向图欧拉道路判别条件:底图连通,入度不等于出度的点的个数小于等于二,且恰好一个点入度比出度大一,作为终点。另一个点出度比入度大一,作为起点。如若所有点入度等于出度,则构成欧拉回路。由于数据范围较小,这里采用较易理解的邻接矩阵存图。但要注意,一遍的图论题往往需要采取邻接表及链式前向星的方式存储。

代码:

/*欧拉道路*/
/*将单词看为有向边,问题转化为图是否存在欧拉道路*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#define endl "\n"
using namespace std;
const int maxn = 26;
int graph[maxn][maxn];
int vis[maxn];
bool flag=true;
int in[maxn],out[maxn];
int start=-1,comp=-1;
int cnt=0;
void init(void)
{memset(graph,0,sizeof(graph));memset(vis,0,sizeof(vis));memset(in,0,sizeof(in));memset(out,0,sizeof(out));flag=true;start=-1;comp=-1;cnt=0;
}
void dfs(int u)
{vis[u]=1;for(int i=0;i<maxn;i++){if(graph[u][i]&&!vis[i]){dfs(i);}}
}
void judge(void)//判断是否完全遍历
{for(int i=0;i<maxn;i++){if(in[i]&&!vis[i]){flag=false;}if(out[i]&&!vis[i]){flag=false;}}
}
int main(void)
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int t;cin>>t;while(t--){int N;cin>>N;init();while(N--){string s;cin>>s;graph[s[0]-'a'][s[s.length()-1]-'a']=1;out[s[0]-'a']++;in[s[s.length()-1]-'a']++;}for(int i=0;i<maxn;i++){if(in[i]!=out[i]){if(in[i]-out[i]==1){comp=i;}else if(out[i]-in[i]==1){start=i;}else{flag=false;}cnt++;}}if(cnt==0)//欧拉回路{for(int i=0;i<maxn;i++){if(in[i]==out[i]&&in[i]){dfs(i);judge();break;}}}else if(cnt==2)//正好存在两奇点的欧拉道路{if(start!=-1&&comp!=-1){dfs(start);judge();}else{flag=false;}}else//不存在欧拉道路{flag=false;}if(flag){cout<<"Ordering is possible."<<endl;}else{cout<<"The door cannot be opened."<<endl;}}return 0;
}

H.

枚举二叉树,回溯法框架。

我们将木棍与砝码都看作结点,则原题转化为满足特殊要求的二叉树横向距离最长,且严格小于r。这里我们采用自顶向下构造的方式,高效枚举子集。用1来表示取用该砝码,0表示不取。

则我们首先应当承认这样一个事实:每种取砝码的方式都可以用唯一的二进制数来表示.根节点即为全集。root=ALL_BITS=(1<<n)-1;枚举左子树所取的砝码,则右子树所取砝码即为左子树二进制数的补集。递归求解即可,自定义结构体node,成员变量表示其现在距离根节点的最大左右距离,也即子天平左右臂长。那么,当前结点的左右臂长有如下转移方程。

t.left=max(T[left][i].left+d1,T[right][j].left-d2);
t.right=max(T[left][i].right-d1,T[right][j].right+d2);

其中,d1,d2.根据力矩平衡原理算出。

d1=sum[right]/sum[subset];

d2=sum[left]/sum[subset];

right 和left即为当前正在枚举的子集

sum[i]为当前子集i总重量

subset为此时的全集

如若算出的当前结点臂长之和小于r,则进一步记录结点,同时更新答案。

如若当前集合没有子集,则说明此时的集合为叶子结点权值。当前天平左右臂长用构造函数初始化为空即可。

这里的函数命名为dfs正是因为程序是深度优先遍历整颗解答树的。

代码实现:

//自顶向下求解,高效枚举子集
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<iomanip>
#define endl "\n"
using namespace std;
using ll = long long;
const int maxn = 10;
int vis[1<<maxn];
double sum[1<<maxn];
int n;
double r,W[maxn];
struct node
{double left,right;//当前结点距离根节点的左/右最长距离node()//构造函数{this->left=0.0;this->right=0.0;}
};
vector<node> T[1<<maxn];
void dfs(int subset)
{if(vis[subset])//已搜索则直接返回{return;}vis[subset]=1;//标识为已搜索bool have_subtree=false;for(int left=subset&(subset-1);left;left=(left-1)&subset)//枚举子集{have_subtree=true;int right=subset^left;double d1=sum[right]/sum[subset];double d2=sum[left]/sum[subset];dfs(left);dfs(right);for(int i=0;i<T[left].size();i++){for(int j=0;j<T[right].size();j++){node t;t.left=max(T[left][i].left+d1,T[right][j].left-d2);t.right=max(T[left][i].right-d1,T[right][j].right+d2);if(t.left+t.right<r)//合法则存储当前结点T[subset].push_back(t);}}}if(!have_subtree)//叶子结点{T[subset].push_back(node());}
}
void solve(void)
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int t;cin>>t;while(t--){cin>>r>>n;for(int i=0;i<n;i++){cin>>W[i];}for(int i=0;i<(1<<n);i++){sum[i]=0;T[i].clear();for(int j=0;j<n;j++)//计算sum数组{if(i&(1<<j)){sum[i]+=W[j];}}}memset(vis,0,sizeof(vis));int root=(1<<n)-1;//根节点dfs(root);//递归求解double ans= -1;for(int i=0;i<T[root].size();i++)//最大化答案{ans=max(ans,T[root][i].left+T[root][i].right);}if(ans!=-1)cout<<fixed<<setprecision(10)<<ans<<endl;//保留10位小数elsecout<<-1<<endl;//无解}
}
int main(void)
{solve();return 0;
}

【计科二班】编程测试题解相关推荐

  1. 计科二班摸底考试题解

    A 本题为今年西南民大校赛的一道签到题 只需逐行循环读入字符串,并统计":w"的个数即可,注意程序有空格间断,所以使用gets读入 代码: #include<stdio.h& ...

  2. 计科1111-1114班第一周讲义、课外作业(截止日期:2014年3月12日23点-周三晚,学委飞信通知同学)

    很高兴能够认识大家,并和大家一起学习<算法设计与分析>课程.根据"学习金字塔"理论,"小组讨论.实践练习.向他人讲授/学以致用"是三种主动学习形式. ...

  3. 2017《JAVA》预备作业 计科1501班 王奕开

    2017<JAVA>预备作业 计科1501班 王奕开 1.阅读邹欣老师的博客,谈谈你期望的师生关系是什么样的? 亦师亦友,课下多多交流,和学生探讨经验,和蔼可亲. 2.你有什么技能(学习, ...

  4. 这是一个作业,还是第一个作业(计科6班 郭家豪)

    自我介绍: 我是来自2017级计科6班的郭家豪.我对任何一件事物的设计充满热情,一张图片.一段视频,一项任务过程等,我都愿意花上一段时间去让它变得更好.在大学我选择了计科,不仅因为我对计算机世界充满好 ...

  5. 武汉大学计算机学院学生寝,多彩青春一路同行——记武大计算机学院计科2班...

    荆楚网(湖北日报)(记者 龙华)拨动按钮,传来一段清脆的铃音.眼前的只是一块其貌不扬的电路板,但是它却能通过耳机向使用者报告当前所在的位置.有了它,盲人便不会在车水马龙的路上迷失方向. 这是武汉大学计 ...

  6. java第六次作业 计科1501班 张鹏

    java 第六次作业 计科1501 张鹏 1.用思维导图对本周的学习内容进行总结. 2.当程序中出现异常时,JVM会依据方法调用顺序依次查找有关的错误处理程序.可使用printStackTrace和g ...

  7. 2022南阳理工计科ACM计科TC招新热身赛题解

    这真的是一场模拟赛. 这场比赛整体难度不是很难,有很多都是签到题,并且还有一些题是之前题的变形,大家可以看一下题解去找一下自己比赛时哪一些是没有想明白,或者没办法实现的思路是怎么去实现的 思路是一方面 ...

  8. 21计科一班题单2---题解

    题单2-题解 P5710 数的性质 题目描述 一些数字可能拥有以下的性质: 性质 1:是偶数: 性质 2:大于 4 且不大于 12. 小A 喜欢这两个性质同时成立的数字:Uim 喜欢这至少符合其中一种 ...

  9. 计科1111-1114班第三周讲义、课外作业(截止日期:2014年3月27日23点-周四晚,学委飞信通知同学)

    第三周,我们主要探讨了 哈希算法 与 分治法.分治法是一个通用的算法框架,很多我们日常生活中接触到的算法都可以归类到分治法中. 本周重点 1. 哈希算法及其应用--MD5.大家应该明白哈希算法的主要三 ...

最新文章

  1. 2021-2027年中国一氧化氮行业市场研究及前瞻分析报告
  2. WMI Series :管理对象的信息查询和方法访问
  3. pythonweb开发-Python Web开发从入门到精通
  4. How To Open An URL In Android’s Web Browser
  5. 十进制转二进制、二进制转十进制
  6. 编译原理习题(含答案)
  7. Framework打包
  8. php 发邮件附件pdf,php – 使用TCPDF发送电子邮件附件 | 码农网
  9. 关于rocketmq的配置启动
  10. Redhat7系统root用户密码破解
  11. 【历史上的今天】1 月 14 日:IBM 计算机先驱诞生;Windows 7 寿终正寝;诺基亚收购阿尔卡特
  12. linux访问mdio接口函数,MII 接口解析(三)GPIO 模拟 MDIO 接口使用代码
  13. 开源开放 | OpenKG发布cnSchema重构版本
  14. linux中无损gpt转mbr,如何快速实现免重装无损磁盘MBR转GPT?
  15. 中国临沂白沙埠第四届洋葱文化节开幕
  16. 分享网页微信防撤回插件
  17. 【玩转CSS】盒子模型
  18. 树莓派 博通BCM2835芯片手册
  19. CF1548D2 Gregor and the Odd Cows (Hard)
  20. 信号归一化功率_MQAM信号调制方式自动识别方法

热门文章

  1. sqlitestudio和mysql_sqlitestudio怎么用 sqlitestudio使用方法图文详解
  2. 好奇那些进了大厂的程序员面试前都做了哪些准备?Android大厂面试官全套教程教你:这样准备面试顺利拿到offer
  3. 作业帮面经(已拿offer)
  4. 5.1.2全景声音箱摆位_全景声音响系统,音箱应该如何摆位?(5.1.2、5.1.4篇)
  5. 3D模型欣赏:永恒之王异形机甲风
  6. 出轨的是老公为什么要老婆做出改变
  7. java程序员一般用什么笔记本_购买适合程序员编程开发用的笔记本电脑的几点建议...
  8. muduo实现finger服务
  9. SDKMAN-Linux软件开发工具包
  10. adb 模拟按键,调试按键,android测试可以用