细胞色素(Cytochorme)训练4
题意:求判断:n/i(向下取整),i从1到n的和是奇数还是偶数。
程磊说这题是整除分块,但实际上打表找规律非常简单。
#include<bits/stdc++.h>
#define mem(a,b) memset((a),b,sizeof(a))
#define de cout<<endl<<endl<<endl
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=100010;
using namespace std;
ll n;
int main()
{
int TT=0;
int T;scanf("%d",&T);
while(T--)
{
scanf("%lld",&n);
ll k=sqrt(n);
if(k%2==1)
printf("Case %d: odd\n",++TT);
else
printf("Case %d: even\n",++TT);
}
return 0;
}
题意:给你A地的时间,然后给你AB两地所在时区,让你计算B地的时间。
有几个坑点,就是小时的取值范围是1到12,半夜12点表示为12:00AM,中午12:00表示为12:00PM。并且半夜12点是新的一天的开始。
还有就是,我的代码写的太烂了,又臭又长。看了别人的代码,发现自己是真的烂。
下面是我最开始写的代码:(又臭又长)
#include <bits/stdc++.h>
using namespace std;
char a[110],b[110],c[110];
char m[110];
int main()
{
int T;scanf("%d",&T);
int TT=0;
while(T--)
{
getchar();
gets(a);
int p1,p2;
int len=strlen(a);
//开始就是这里写错了
// if(strcmp(a,"12:00 AM")==0)
// strcpy(a,"0:00 AM");
// if(strcmp(a,"12:00 PM")==0)
// strcpy(a,"0:00 PM");
for(int i=0;i<len;i++)
{
if(a[i]==':')
p1=i;
}
int h;
if(p1==1)
h=a[0]-'0';
else
h=(a[0]-'0')*10+(a[1]-'0');
if(h==12)
h=0;
for(int i=0;i<len;i++)
if(a[i]==' ')
p2=i;
for(int i=p1+1;i<=p2-1;i++)
m[i-p1-1]=a[i];
if(a[p2+1]=='P')
h+=12;
scanf("%s%s",b,c);
int q1,q2;
if(strcmp(b,"Beijing")==0)
q1=8;
if(strcmp(b,"Washington")==0)
q1=-5 ;
if(strcmp(b,"London")==0)
q1=0;
if(strcmp(b,"Moscow")==0)
q1=3;
if(strcmp(c,"Beijing")==0)
q2=8;
if(strcmp(c,"Washington")==0)
q2=-5 ;
if(strcmp(c,"London")==0)
q2=0;
if(strcmp(c,"Moscow")==0)
q2=3;
printf("Case %d: ",++TT);
int q=q2-q1;
h+=q;
if(h>=24)
{
h-=24;
printf("Tomorrow ");
if(h>=12)
{
if(h-12==0)
printf("12:");
else
printf("%d:",h-12);
for(int i=0;i<p2-p1-1;i++)
printf("%c",m[i]);
printf(" PM\n");
}
else
{
if(h==0)
printf("12:");
else
printf("%d:",h);
for(int i=0;i<p2-p1-1;i++)
printf("%c",m[i]);
printf(" AM\n");
}
continue;
}
if(h<0)
{
h+=24;
printf("Yesterday ");
if(h>=12)
{
if(h-12==0)
printf("12:");
else
printf("%d:",h-12);
for(int i=0;i<p2-p1-1;i++)
printf("%c",m[i]);
printf(" PM\n");
}
else
{
if(h==0)
printf("12:");
else
printf("%d:",h);
for(int i=0;i<p2-p1-1;i++)
printf("%c",m[i]);
printf(" AM\n");
}
continue;
}
printf("Today ");
if(h>=12)
{
if(h-12==0)
printf("12:");
else
printf("%d:",h-12);
for(int i=0;i<p2-p1-1;i++)
printf("%c",m[i]);
printf(" PM\n");
}
else
{
if(h==0)
printf("12:");
else
printf("%d:",h);
for(int i=0;i<p2-p1-1;i++)
printf("%c",m[i]);
printf(" AM\n");
}
continue;
}
return 0;
}
然后下面是精简版的:(代码量少,时间还快了一点点)
#include<bits/stdc++.h>
using namespace std;
map<string,int> mp;
string a,b,p;
int main()
{
mp["Beijing"]=8;
mp["Washington"]=-5;
mp["London"]=0;
mp["Moscow"]=3;
int TT=0;
int T;scanf("%d",&T);
int h,m;
while(T--)
{
scanf("%d:%d",&h,&m);
cin>>p;
if(p=="PM"&&h!=12)
h+=12;
if(p=="AM"&&h==12)
h-=12;
cin>>a>>b;
h+=(mp[b]-mp[a]);
printf("Case %d: ",++TT);
if(h>=24)
{printf("Tomorrow ");h-=24;}
else if(h<0)
{printf("Yesterday ");h+=24;}
else
printf("Today ");
if(h>12)
printf("%d:%02d ",h-12,m);
else if(h>0)
printf("%d:%02d ",h,m);
else
printf("12:%02d ",m);
if(h>=12)
printf("PM\n");
else
printf("AM\n");
}
return 0;
}
题意:看别人的吧,懒得写了。这题如果读懂了,认真想一下,真的超简单。
https://blog.csdn.net/aiyouyou_/article/details/89790003
#include<bits/stdc++.h>
#define mem(a,b) memset((a),b,sizeof(a))
#define de cout<<endl<<endl<<endl
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=100010;
using namespace std;
int n;
ll a[1000010];
int main()
{
int TT=0;
int T;scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
ll ans=0;
for(int i=1;i<=n;i++)
{
if(i>=2&&(a[i]-2)>=0)
ans=ans^(a[i]-2);
}
printf("Case %d: %lld\n",++TT,ans);
}
return 0;
}
题意:给你n个数a[i],让你把这些数分成两堆,问能够使两堆数的和都大于等于1/2,如果能的话还要输出方案。
归并一下。
实际上当时程磊的代码差一点就对了,只需要把100改成100000就行了......
#include<bits/stdc++.h>
#define mem(a,b) memset((a),b,sizeof(a))
#define de cout<<endl<<endl<<endl
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=1e5+10;
using namespace std;
struct node{
int v,id,f;
}a[N+10];
bool cmp1(node a1,node a2){
return a1.v<a2.v;
}
bool cmp2(node a1,node a2){
return a1.id<a2.id;
}
int n,cnt[N+10];
bool ok(int n,int v)
{
v--;
while(v--)
n/=2;
if(n>0)
return true;
return false;
}
int get(int n,int k)
{
while(k--)
n/=2;
return n;
}
int main()
{
int T;scanf("%d",&T);int TT=0;
while(T--)
{
scanf("%d",&n);
mem(cnt,0);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].v);
a[i].f=0;
a[i].id=i;
if(a[i].v>=N) continue;
cnt[a[i].v]++;
}
for(int i=N;i>=1;i--)
cnt[i-1]+=cnt[i]/2;
if(cnt[0]==0) {printf("Case %d: NO\n",++TT);continue;}
printf("Case %d: YES\n",++TT);
sort(a+1,a+n+1,cmp1);
mem(cnt,0);
for(int i=n;i>=1;i--)
{
a[i].f=1;
if(a[i].v>N)
continue;
cnt[a[i].v]++;
if(ok(cnt[a[i].v],a[i].v))
break;
if(i!=1)
{
if(a[i].v!=a[i-1].v)
cnt[a[i-1].v]=get(cnt[a[i].v],a[i].v-a[i-1].v);
}
}
sort(a+1,a+n+1,cmp2);
for(int i=1;i<=n;i++)
printf("%d",a[i].f);
puts("");
}
return 0;
}
题意:懒得写了,看别人的吧。https://blog.csdn.net/dillonh/article/details/96308618
#include<bits/stdc++.h>
#define mem(a,b) memset((a),b,sizeof(a))
#define de cout<<endl<<endl<<endl
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=100010;
using namespace std;
int n,m;
ll a[100010],b[100010];
int c[100010];
ll ans1,ans2,ans;
bool cmp(ll a1,ll a2)
{
return a1>a2;
}
int main()
{
int TT=0;
int T;scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(int i=1;i<=m;i++)
scanf("%lld",&b[i]);
for(int i=1;i<=m;i++)
scanf("%d",&c[i]);
ans1=0;ans2=0;
int p,q,f,ff;
//打普通的怪,直接对人造成杀伤 优先用大的打小的
sort(a+1,a+n+1,cmp);
sort(b+1,b+m+1);
p=1;q=1;
for(int i=p;i<=n;i=p)
{
if(q>m)
break;
for(int j=q;j<=m;j=q)
{
if(a[i]<=b[j]||c[j]==1)
{q++;continue;}
ans1+=(a[i]-b[j]);
p++;
q++;
break;
}
}
//把怪全打死,然后打人造成杀伤 优先用大的打大的
sort(a+1,a+n+1,cmp);
sort(b+1,b+m+1,cmp);
p=1;q=1;f=0;
for(int i=p;i<=n;i=p)
{
if(q>m)
break;
for(int j=q;j<=m;j=q)
{
if(a[i]<b[j]) //不可能把怪全打死
{p++;f++;break;}
else if(a[i]==b[j])
{p++;q++;a[i]=0;break;}
else
{
if(c[j]==0)
{ans2+=a[i]-b[j];b[j]=0;a[i]=0;}
else
{b[j]=0;a[i]=0;}
p++;q++;
break;
}
}
if(f)
break;
}
if(f==0) //已经成功的把怪全打死了
{
for(int i=1;i<=n;i++)
ans2+=a[i];
}
ans=max(ans1,ans2);
printf("Case %d: %lld\n",++TT,ans);
}
return 0;
}
题意:有两个整数p和q,q的初始值为2,p是输入的数。p表示你赢的的概率为百分之p,如果赢了的话,你有百分之q的概率能拿到你想要的东西,如果你赢了但没有拿到想要的东西,那就让q加上2,如果你没赢,那就让q加上1.5。问你拿到想要的东西所需的比赛次数的期望是多少。
思路:dp。可以直接dp,也可以打表做,不过时间都挺快的,差不多都是15ms过。实际上我感觉很多dp都很简单,当时想不起来主要是没想起来它的状态,如果状态想起来了,那转移方程应该特别好些,以后要大胆的猜想状态......
直接做:
#include<bits/stdc++.h>
#define mem(a,b) memset((a),b,sizeof(a))
#define de cout<<endl<<endl<<endl
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=100010;
using namespace std;
map<pair<int,int>,double> mp;
double solve(int p,int q)
{
if(q>=200)
return 100.0/p;
if(mp.count(make_pair(p,q))!=0)
return mp[make_pair(p,q)];
mp[make_pair(p,q)]=0.01*p*(0.01*q/2+0.01*(200.0-q)/2*(solve(p,q+4)+1))+0.01*(100.0-p)*(solve(p,q+3)+1);
return mp[make_pair(p,q)];
}
int main()
{
int T;scanf("%d",&T);int TT=0;
for(int i=1;i<=100;i++)
{
int p=i;
scanf("%d",&p);
printf("Case %d: %.6f\n",++TT,solve(p,4));
}
return 0;
}
打表做:
#include<bits/stdc++.h>
#define mem(a,b) memset((a),b,sizeof(a))
#define de cout<<endl<<endl<<endl
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=100010;
using namespace std;
double ans[110]={0,130.753045,79.205364,61.164050,51.603369,45.502018,41.175611,37.895063,35.290824,33.154035,31.356819,29.815932,28.474488,27.292070,26.239021,25.292991,24.436754,23.656775,22.942244,22.284399,21.676050,21.111233,20.584950,20.092974,19.631705,19.198053,18.789347,18.403267,18.037784,17.691118,17.361696,17.048125,16.749164,16.463705,16.190756,15.929421,15.678896,15.438450,15.207420,14.985205,14.771253,14.565062,14.366172,14.174159,13.988633,13.809236,13.635634,13.467523,13.304615,13.146648,12.993376,12.844569,12.700013,12.559511,12.422874,12.289928,12.160509,12.034465,11.911649,11.791927,11.675170,11.561258,11.450076,11.341518,11.235482,11.131871,11.030594,10.931564,10.834701,10.739926,10.647165,10.556348,10.467408,10.380281,10.294907,10.211227,10.129187,10.048734,9.969817,9.892388,9.816402,9.741813,9.668581,9.596664,9.526025,9.456624,9.388428,9.321402,9.255512,9.190728,9.127018,9.064355,9.002708,8.942053,8.882362,8.823610,8.765774,8.708830,8.652755,8.597528,8.543127};
int main()
{
int T;scanf("%d",&T);int TT=0;
while(T--)
{
int p;
scanf("%d",&p);
printf("Case %d: %.6f\n",++TT,ans[p]);
}
return 0;
}
题意:给你一个圆锥,然后再给你一个点的位置和它的速度,问经过多长时间它能打到圆锥上,题目数据保证开始时点在圆锥外,并且保证点一定能打到圆锥上。
思路:列除圆锥的表面方程,还有点的参数方程,带入整理解出时间就行了,还挺简单的,主要是不知道圆锥的表面方程,知道的话应该挺简单的。
下面是粗略的计算过程:
代码:
#include<bits/stdc++.h>
#define mem(a,b) memset((a),b,sizeof(a))
#define de cout<<endl<<endl<<endl
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=100010;
using namespace std;
double r,h,xx,yy,zz,vx,vy,vz;
int main()
{
int T;scanf("%d",&T);int TT=0;
while(T--)
{
scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&r,&h,&xx,&yy,&zz,&vx,&vy,&vz);
double a,b,c;
a=vz*vz-h*h*(vx*vx+vy*vy)/(r*r);
b=2*zz*vz-2*h*vz-h*h*(2*xx*vx+2*yy*vy)/(r*r);
c=zz*zz+h*h-2*h*zz-h*h*(xx*xx+yy*yy)/(r*r);
double t1,t2;
t1=-1*(b+sqrt(b*b-4*a*c))/(2*a);
t1=-1*(b-sqrt(b*b-4*a*c))/(2*a);
double t=max(t1,t2);
printf("Case %d: %.6f\n",++TT,t);
}
return 0;
}