上海大学程序设计联赛A-C E-F
从简单的开始。
C F B E A G
C:签到题。
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
double t,sum,n,flag,add;
char c;
cin>>t;
while(t--)
{
sum=0;
cin>>n;
c=getchar();
for(add=0;add<n;add++)
{
flag=1;
c=getchar();
while(c!=10)
{
if(c=='2'&&flag)
{
flag=0;
sum++;
}
c=getchar();
}
}
sum=sum/n;
printf("%lf\n",sum);
}
return 0;
}F:记每次操作的得分为p1,p2,p3...易证p1>=p2>=p3>=...,又有第一个人的得分为p1+p3+p5+...,第二个人的得分为p2+p4+p6+...故第一个人必胜。
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
cout<<"Yes"<<endl;
}
return 0;
}B:简单的运算。写复杂了,还能简化,并且可以通过数组实现多重括号的运算。
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
char p[100002]={0};
int main()
{
long long flag=0,sum1=0,sum2=0,add=0,n,times,k,flag2;
char c;
c=getchar();
while(c!=10)
{
p[add++]=c;
c=getchar();
}
n=add;
for(add=0;add<n;add++)
{
times=0;
flag2=0;
if(flag==0)
{
if(p[add]=='C'||p[add]=='H'||p[add]=='O')
{
if(p[add]=='C') k=13;
if(p[add]=='H') k=1;
if(p[add]=='O') k=17;
while(p[add+1]<='9'&&p[add+1]>='0')
{
times=times*10;
times+=p[add+1]-'0';
add++;
flag2=1;
}
if(!flag2)
times=1;
sum1+=k*times;
}
else if(p[add]=='(')
flag=1;
}
else
{
if(p[add]=='C'||p[add]=='H'||p[add]=='O')
{
if(p[add]=='C') k=13;
if(p[add]=='H') k=1;
if(p[add]=='O') k=17;
while(p[add+1]<='9'&&p[add+1]>='0')
{
times=times*10;
times+=p[add+1]-'0';
add++;
flag2=1;
}
if(!flag2)
times=1;
sum2+=k*times;
}
else if(p[add]==')')
{
flag=0;
while(p[add+1]<='9'&&p[add+1]>='0')
{
times=times*10;
times+=p[add+1]-'0';
add++;
flag2=1;
}
if(!flag2)
times=1;
sum1+=sum2*times;
sum2=0;
}
}
}
printf("%lld",sum1);
return 0;
}E:体力题。首先将十六进制转化为二进制,通过二分查找找到对应数值,再转回十六进制。
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int s[100000],r[8],zz[32],yy;
long long j[100000];
int main()
{
long long k[31];
k[0]=1;
int n,m,p,add,x,sum;
char c;
scanf("%d %d %d",&n,&m,&p);
for(add=1;add<=30;add++)
{
k[add]=k[add-1]*2;
}
for(add=0;add<k[m-p];add++)
{
scanf("%lld",&j[add]);
j[add]=j[add]*100000+add;
}
sort(j,j+k[m-p]);
for(add=0;add<k[m-p];add++)
{
s[add]=j[add]%100000;
j[add]=j[add]/100000;
}
cin>>x;
while(x--)
{
c=getchar();
for(add=0;add<8;add++)
{
c=getchar();
if(c<='9'&&c>='0')
r[add]=c-'0';
else
r[add]=c-'A'+10;
}
for(add=0;add<8;add++)
{
zz[add*4]=r[add]/8;
if(zz[add*4]) r[add]-=8;
zz[add*4+1]=r[add]/4;
if(zz[add*4+1]) r[add]-=4;
zz[add*4+2]=r[add]/2;
if(zz[add*4+2]) r[add]-=2;
zz[add*4+3]=r[add];
}
sum=0;
for(add=0;add<32-p;add++)
{
sum=sum*2;
sum+=zz[add];
}
for(add=0;add<k[m-p];add++)
{
if(sum==j[add])
break;
}
if(add==k[m-p])
{
cout<<"interrupt!"<<endl;
continue;
}
else
{
yy=s[add];
for(add=0;add<32-p;add++)
{
if(yy>=k[32-p-add-1])
{
zz[add]=1;
yy-=k[32-p-add-1];
}
else
zz[add]=0;
}
for(add=0;add<8;add++)
{
r[add]=0;
for(int add2=0;add2<4;add2++)
{
r[add]=r[add]*2;
r[add]+=zz[add*4+add2];
}
if(r[add]<10)
cout<<r[add];
else
printf("%c",r[add]-10+'A');
}
cout<<endl;
}
}
return 0;
}A:从这题开始略有难度。首先可以将题转化为 将n/k分解成三个互质的且不为一的数。
令n=n/k。考虑n为偶数,则三个数一定为偶+奇+奇,不妨设a=2,b=n/2-1,c=n/2+1,如果b和c为偶数则b--,c++。
若n为奇数,考虑n%3==0,则a=n/3-2,b=n/3,c=n/3+2。考虑n%3==2,则a=(n-2)/3-2,b=(n-2)/3,c=(n-2)/3
+2+2。此时会出现a与c都是3的倍数的情况,则a-=2,b+=2。考虑n%3==4也就是n%3==1,a=(n-4)/3-2,b=(n-4)/3+2,c=(n-4)/3+2+2。此时会出现a与c都是3的倍数的情况,则b-=2,c+=2。
易证使用上面的方法不会出现abc不互质的情况,但需要排除abc为1的情况,即n<=9,n=11,13,17
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
long long t,n,k,a,b,c;
cin>>t;
while(t--)
{
cin>>n>>k;
if(n%k!=0)
{
printf("-1 -1 -1\n");
continue;
}
n=n/k;
if(n<=9||n==11||n==13||n==17)
{
printf("-1 -1 -1\n");
continue;
}
if(n%2==0)
{
a=2;
b=(n-2)/2-1;
c=(n-2)/2+1;
if(b%2==0)
{
b--;
c++;
}
}
else
{
if(n%3==0)
{
a=n/3-2;
b=n/3;
c=n/3+2;
}
else if(n%3==2)
{
a=(n-2)/3-2;
b=(n-2)/3;
c=(n-2)/3+2+2;
if(c%3==0)
{
a-=2;
b+=2;
}
}
else if(n%3==1)
{
a=(n-4)/3-2;
b=(n-4)/3+2;
c=(n-4)/3+2+2;
if(c%3==0)
{
b-=2;
c+=2;
}
}
}
a=a*k,b=b*k,c=c*k;
printf("%lld %lld %lld\n",a,b,c);
}
}G:没有全过,回头再找一下疏漏。
大体思路是用dp。将问题转化在2n+1个数中取n个不相邻的数,找最大的和。假设取1 3 5 7...2n-1,那么可以将问题转化为:将两个空格插入已经取好的数列中。即:将两个空格安排再2n+1个数中间。因此设立数组zz[200020][3],其中zz[a][b]表示到第a个数已经用了b个空格的情况下,可能的最大值。
例:有1 3 6 2 4 8 9 7
zz[1][0]=1
zz[1][1]=-1e17
zz[1][2]=-1e17 注意到取第一个数的话,不可能是已经使用了一个或两个空格的状态
zz[2][0]=-1e17 注意到取第二个数的话,不可能是没有使用空格的状态
zz[2][1]=3
zz[2][2]=-1e17
zz[3][0]=zz[1][0]+6=7 不使用空格,那么应该取第1 3个数
zz[3][1]=-1e17
zz[3][2]=6 两个空格,即第1和第2都不取,直接取第3
zz[4][1]=max(zz[2][1],zz[1][0])+2 要么从1跳过来,要么从2顺延过来。换句话说,一种是取1 4,一种是取2 4,两种都是用了一个空格的情况。
zz[5][0]=zz[3][0]+4=11 取第1 3 5个数
zz[5][2]=max(zz[3][2],zz[1][0])+4 要么从1跳过来,要么从3顺延过来。换句话说,一种是取1 5,一种是取3 5,两种都是用了两个空格的情况。
...
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
long long j[200020],v[200020]={0},zz[200020][3];
int main()
{
long long find(int left,int right);
long long n,x,add,lmax,lmm,rmax,rmm,sumt,summax=-1e16;
cin>>n>>x;
for(add=1;add<=n;add++)
scanf("%lld",&j[add]);
if(n%2==0)
{
sumt=0;
for(add=1;add<n;add+=2)
{
sumt+=j[add];
v[add]=1;
}
summax=sumt;
for(add=n-1;add>0;add-=2)
{
sumt-=j[add];
sumt+=j[add+1];
v[add]=0;
v[add+1]=1;
if(summax<sumt&&v[x]) summax=sumt;
}
cout<<summax;
return 0;
}
if(x%2==0)
{
sumt=0;
for(add=2;add<=n;add+=2)
sumt+=j[add];
summax=sumt;
for(add=2;add<x;add+=2)
{
sumt-=j[add];
sumt+=j[add-1];
if(sumt>summax) summax=sumt;
}
sumt=summax;
for(add=n-1;add>x;add-=2)
{
sumt-=j[add];
sumt+=j[add+1];
if(sumt>summax) summax=sumt;
}
cout<<summax;
return 0;
}
if(x!=1&&x!=n)
{
sumt=0;
for(add=1;add<x;add+=2)
sumt+=j[add];
lmax=sumt;
sumt=0;
for(add=x+2;add<=n;add+=2)
sumt+=j[add];
rmax=sumt;
lmm=find(1,x-2);
rmm=find(x+2,n);
if(lmm+rmax>rmm+lmax) summax=lmm+rmax;
else summax=rmm+lmax;
cout<<summax+j[x];
return 0;
}
if(x==n)
cout<<find(1,n-2)+j[x];
else
cout<<find(3,n)+j[x];
return 0;
}
long long find(int left,int right)
{
long long max(long long a,long long b);
long long max3(long long a,long long b,long long c);
long long n=right-left+1,add,ans;
zz[left][0]=j[left];
zz[left+1][1]=j[left+1];
zz[left+2][0]=zz[left][0]+j[left+2];
zz[left+2][2]=j[left+2];
for(add=left+3;add<=right;add++)
{
if((add-left)%2==1)
zz[add][1]=max(zz[add-3][0]+j[add],zz[add-2][1]+j[add]);
else
{
zz[add][0]=zz[add-2][0]+j[add];
zz[add][2]=max3(zz[add-4][0]+j[add],zz[add-3][1]+j[add],zz[add-2][2]+j[add]);
}
/*cout<<add<<endl;
for(add2=0;add2<3;add2++) cout<<zz[add][add2]<<" ";
cout<<endl;*/
}
if(n==1) return 0;
if(n==3) return max3(j[left],j[left+1],j[left+2]);
ans=max3(zz[right-2][0],zz[right-1][1],zz[right][2]);
return ans;
}
long long max(long long a,long long b)
{
if(a>=b)
return a;
return b;
}
long long max3(long long a,long long b,long long c)
{
if(a>=b&&a>=c)
return a;
if(b>=c)
return b;
return c;
}
查看12道真题和解析