第一次CF啊,和朋友在C4回来的火车上打的。
当时过了c题,第二天早上起来重新改变了数据变成没过了,呜呜呜呜
A:http://codeforces.com/problemset/problem/801/A
水题
1.记下没有变的时候的VK数量
2暴力枚举每个字符变换,取最大值~即可
#include <iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
using namespace std;
char x[120];
char y[120];
char ans[120];
int main()
{
int n1,n2;
scanf("%s%s",x,y);
n1=strlen(x); n2=strlen(y);
if(n1!=n2) {printf("-1\n");return 0;}
bool flag=0;
for(int i=0;i<n1;i++)
{
if(y[i]>x[i]) {flag=1;break;}
}
if(flag) {printf("-1\n");return 0;}
for(int i=0;i<n1;i++)
{
if(y[i]<x[i]) ans[i]=y[i];
else
ans[i]=x[i];
}
for(int i=0;i<n1;i++)
{
printf("%c",ans[i]);
}
printf("\n");
return 0;
}
#include <iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
char s[120];
int main()
{
int n;
scanf("%s",s);
n =strlen(s);
int ans=0;
for(int i=0;i<n-1;i++)
{
if(s[i]=='V'&&s[i+1]=='K') {ans++;i++;}
}
for(int t=0;t<n;t++)
{
if(s[t]=='V') s[t]='K';
else s[t]='V';
int flag=0;
for(int i=0;i<n-1;i++)
{
if(s[i]=='V'&&s[i+1]=='K') {flag++;i++;}
}
if(flag>ans) ans=flag;
if(s[t]=='V') s[t]='K';
else s[t]='V';
}
printf("%d\n",ans);
return 0;
}
B http://codeforces.com/problemset/problem/801/B
水题
1.如果y串中有比x串大的,显然不成立(直接输出-1)
2.如果(y[i]<x[i]) s[i]=y[i] ; else s[i]=x[i];(这里直接让相等,偷懒)
#include <iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
using namespace std;
char x[120];
char y[120];
char ans[120];
int main()
{
int n1,n2;
scanf("%s%s",x,y);
n1=strlen(x); n2=strlen(y);
if(n1!=n2) {printf("-1\n");return 0;}
bool flag=0;
for(int i=0;i<n1;i++)
{
if(y[i]>x[i]) {flag=1;break;}
}
if(flag) {printf("-1\n");return 0;}
for(int i=0;i<n1;i++)
{
if(y[i]<x[i]) ans[i]=y[i];
else
ans[i]=x[i];
}
for(int i=0;i<n1;i++)
{
printf("%c",ans[i]);
}
printf("\n");
return 0;
}
C http://codeforces.com/problemset/problem/801/C
直接二分答案就可以了,这里把r直接看成1e11,先判断r是否可以,如果可以说明无上限
else 二分1000次即可
#include <iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
int n;
double p;
double a[100100];
double b[100100];
bool judge(double temp)
{
double sum=0;
for(int i=0;i<n;i++)
{
if(a[i]*temp>b[i]) sum+=(a[i]*temp-b[i]);
}
if(sum>temp*p) return 0;
return 1;
}
int main()
{
double l=0,r=1e11,mid;
scanf("%d%lf",&n,&p);
for(int i=0;i<n;i++)
{
scanf("%lf%lf",&a[i],&b[i]);
}
if(judge(r))
{
printf("-1\n");
return 0;
}
for(int i=0;i<1000;i++)
{
mid=(l+r)/2;
if(judge(mid)) l=mid;
else r=mid;
}
printf("%.9lf\n",(l+r)/2);
return 0;
}
D http://codeforces.com/problemset/problem/801/D
显然可知,如果要是凸包退化(即就是出现三点一线的情况)。
只需要移动最小的(点到直线距离)一半(点走一半,线走一半)
这道题真的受教了 刚开始自己做的时候就是傻傻的算点到直线距离公式 ,但一直错。个人觉得没有问题k不存在的时候也判了。
看了大佬的写法
这里有三个点 a,p,q 要算a点到p,q所形成线的距离,
2*h=(向量pa 叉乘 向量 qa)/(p,q的距离) //向量叉积为这三点形成的四边形面积,一半就是三角形面积!
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
const double inf=1e18;
struct point
{
double x,y;
}doc[1020];
double pointdis(const point &a,const point &b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double linedis(const point a, const point p,const point q)
{
struct point pa,pb;
pa.x=p.x-a.x; pa.y=p.y-a.y;
pb.x=q.x-a.x; pb.y=q.y-a.y;//算出到中间点的向量
double temp=pa.x*pb.y-pa.y*pb.x;//做叉积,叉积的意义为两个向量平行四边形的面积
temp/=(2.0);//三角形面积
return fabs(temp/pointdis(p,q));//三角形面积除以底等于高
}
int main()
{
int n;
scanf("%d",&n);
memset(doc,0,sizeof(doc));
for(int i=0;i<n;i++)
{
scanf("%lf%lf",&doc[i].x,&doc[i].y);
}
double ans=inf+10;
for(int i=0;i<n;i++)
{
int p=i-1,q=i+1;
if(p==-1) p=n-1;
if(q==n) q=0;
ans=min(ans,linedis(doc[i],doc[p],doc[q]));
}
printf("%.10f\n",ans);
return 0;
}
E:http://codeforces.com/problemset/problem/801/E
自己使用dfs 尝试了下,结果TLE !
看了大佬的题解,说是DAG最长路+求解线性同余方程 (直接GG)
大佬的想法:
假设我们求出的前缀乘积的顺序是这样的p1,p2,…,pk.产生的序列为a1,a2,…,ak,那麽就一定有,pi−1∗ai≡pi(MOD m)则一定会有 gcd(pi−1,m)∣pi,(按照这个关系在pi−1,与pi 之间建边就是一个DAG)因此我们可以将可以作为前缀乘积的数按照与m的gcd分类,相同gcd值作为顶点,不同gcd值满足整除关系就建一条边,最终形成一个DAG,跑一变最长路就好了.
注意求解同于方程的时候可能会溢出。有乘法.