CF Round#409 Div2 E题DAG最长路+求解线性同余方程以后补

来源:互联网 发布:gta5网际网络连线 编辑:程序博客网 时间:2024/06/09 15:47

第一次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;}

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;}

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;}


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,跑一变最长路就好了. 
注意求解同于方程的时候可能会溢出。有乘法.






0 0