2020CSP-J2普及级第二轮比赛(复赛)题目参考资料1

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

/* T1优秀的拆分:较简单
思路:
1. 仔细读题结合给的例子,可以发现奇数不存要优秀的拆分。

7=2^2+2^1+2^0 就不是一个优秀的拆分,因为1 不是2 的正整数次幂。

2. 偶数
可以通过log2(n)及pow() 可以找到可以拆分的最大数,循环一次次拆分,直到n<2结束。

*/
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,t,x,y;
cin>>n;
if(n<1)
return 0;
if(n%2==1){
cout<<-1<<endl;
return 0;
}
t=n;
while(t>=2){
x=int(log2(t));
y=pow(2,x);
cout<<y<<" ";
t=t-y;
}
return 0;
}
/* T2直播获奖:计数排序
思路:
1. 根据选手的人数不同,实时播报分数线,需要不断的进行排序,因为n<=10^5,
不断排序会超时。

2. 题目中提示:对于所有测试点,每个选手的成绩均为不超过600 的非负整数。

这样可以用计数排序解决超时的问题。

*/
#include<bits/stdc++.h>
using namespace std;
int a[660];
int main(){
int n,w,i,p,x,y;
cin>>n>>w;
for(i=1;i<=n;i++){
scanf("%d",&x);
a[x]++;
y=max(1,(i*w/100));
int t=0;
for(int j=600;j>=0;j--){
t=t+a[j];
if(t>=y){
printf("%d ",j);
break;
}
}
}
return 0;
}
/* T3 表达式;后缀表达式及表达式树
思路:
1. 通过后缀表达式建立表达式树:
2. 遍历后缀表达式字符串:
若读取到数字,生成结点,入栈
若读取到运算符,生成运算符结点,出栈两个结点,分别作为运算符结点的左右孩子,将运算符结点入栈
最后栈顶结点就是表达式树的根结点
*/
#include<bits/stdc++.h>
using namespace std;
string s;
int n;
int a[500010];
int sta[100010],p=0;
int zhi[500010],cnt;
int tree[500010][2];
int what[500010];
int c[500010];
int main(){
getline(cin,s);
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
cnt=n;
for(int i=0;i<s.size();i++){
if(s[i]=='x'){
i++;
int f=0;
while(isdigit(s[i])){
f=f*10+s[i]-'0';
i++;
}
sta[++p]=f;
what[f]=0;
}else if(s[i]=='&'){
what[++cnt]=1;
tree[cnt][1]=sta[p--];
tree[cnt][0]=sta[p--];
a[cnt]=a[tree[cnt][0]]&a[tree[cnt][1]];
sta[++p]=cnt;
}else if(s[i]=='|'){
what[++cnt]=2;
tree[cnt][1]=sta[p--];
tree[cnt][0]=sta[p--];
a[cnt]=a[tree[cnt][0]]|a[tree[cnt][1]];
sta[++p]=cnt;
}else if(s[i]=='!'){
what[++cnt]=3;
tree[cnt][0]=sta[p--];
a[cnt]=!a[tree[cnt][0]];
sta[++p]=cnt;
}
}
c[cnt]=1;
for(int i=cnt;i>n;i--){
int l=tree[i][0],r=tree[i][1];
if(what[i]==1){
if(((!a[l])&a[r])!=a[i])c[l]=c[i];
if((a[l]&(!a[r]))!=a[i])c[r]=c[i];
}else if(what[i]==2){
if(((!a[l])|a[r])!=a[i])c[l]=c[i];
if((a[l]|(!a[r]))!=a[i])c[r]=c[i];
}else if(what[i]==3){
c[l]=c[i];
}
}
int q;
scanf("%d",&q);
while(q--){
int k;
scanf("%d",&k);
printf("%d\n",a[cnt]^c[k]);
}
return 0;
}
/* T4 DP 题目难度不大
思路:按列从前向后走(递推)
1. 小熊的初始位置在左上角,第1例从上向下走
2. 从第2列到第n列从分从上向下走dn[i][j],从下向上走up[i][j]
dn[i][j],up[i][j]两者取大值
*/
#include <bits/stdc++.h>
using namespace std;
const int maxn=1010;
int a[maxn][maxn];
long long up[maxn][maxn],dn[maxn][maxn],f[maxn][maxn];
const long long inf = 1e18+9;
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
}
}
memset(up,inf,sizeof(up));
memset(dn,inf,sizeof(dn));
memset(f,inf,sizeof(f));
f[1][1]=a[1][1];
for(int i=2;i<=n;i++) //第一列赋值
{
f[i][1]=f[i-1][1]+a[i][1];
}
for(int j=2;j<=m;j++) //从第二列开始推
{
dn[1][j]=f[1][j-1]+a[1][j];
for(int i=2;i<=n;i++)
{
dn[i][j] = max(f[i][j-1],dn[i-1][j])+a[i][j];
}
up[n][j]=f[n][j-1]+a[n][j];
for(int k=n-1;k>=1;k--)
{
up[k][j]=max(f[k][j-1],up[k+1][j])+a[k][j];
}
for(int i=1;i<=n;i++)
f[i][j]=max(dn[i][j],up[i][j]);
}
cout<<f[n][m]<<endl;
return 0;
}。

相关文档
最新文档