zoukankan      html  css  js  c++  java
  • VK Cup 2017

    FallDream打的AB都FFT了,只剩一个我打的C,没进前一百,之后看看马拉松复活赛有没机会呗。

    A. Voltage Keepsake

    题目大意:n个东西,每个东西一开始有bi能源,每秒消耗ai能源,每秒可以给一个东西加p能源,秒可以为实数,问至多多少秒内所有东西能源一直为正。(n<=100,000)

    思路:二分答案,随便check一下。不特判无解可能会炸精度。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define lb long double
    inline int read()
    {
        int x;char c;
        while((c=getchar())<'0'||c>'9');
        for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=x*10+c-'0';
        return x;
    }
    #define MN 100000
    int a[MN+5],b[MN+5];
    int main()
    {
        int n=read(),p=read(),t,i;long long cnt=0;
        lb l,r,mid,sum;
        for(i=1;i<=n;++i)cnt+=a[i]=read(),b[i]=read();
        if(cnt<=p)return 0*puts("-1");
        for(t=100,l=0,r=1e12;--t;)
        {
            mid=(l+r)/2;
            for(i=1,sum=0;i<=n;++i)sum+=max((lb)0,a[i]*mid-b[i]);
            (sum>p*mid?r:l)=mid;
        }
        printf("%.10lf",(double)l);
    }

    B. Volatile Kite

    题目大意:给出一个n的点的凸多边形,求一个最大的d,使得每个点任意移动d以内的距离,得到的新多边形边不相撞且仍是凸多边形。(n<=1,000)

    思路:枚举相邻三个点,d不会超过点i+1到点i与点i+2连线距离的一半,复杂度O(n)。

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    inline int read()
    {
        int x,f=1;char c;
        while((c=getchar())<'0'||c>'9')if(c=='-')f=0;
        for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=x*10+c-'0';
        return f?x:-x;
    }
    #define MN 1000
    struct point{double x,y;}p[MN+5];
    double dis(point a){return sqrt(a.x*a.x+a.y*a.y);}
    point operator-(point a,point b){return (point){a.x-b.x,a.y-b.y};}
    double operator*(point a,point b){return a.x*b.y-a.y*b.x;}
    int main()
    {
        int n=read(),i,j;double ans=1e18;
        for(i=0;i<n;++i)p[i].x=read(),p[i].y=read();
        p[n]=p[0];p[n+1]=p[1];
        for(i=0;i<n;++i)ans=min(ans,fabs((p[i+1]-p[i])*(p[i+2]-p[i]))/dis(p[i]-p[i+2]));
        printf("%.10lf",ans/2);
    }

    C. Vulnerable Kerbals

    题目大意:给出m和n个0~m-1内的数,构造一个尽可能长的所有元素都在0~m-1内的数列,使所有前缀积模m不相同且不在n个数中出现过。(0<=n<m<=200,000)

    思路:若前i个数的前缀积为x,前i+1个数的前缀积可以为y当且仅当ax-bm=y有解,即gcd(x,m)|y,若我们让所有满足这个条件的x,y,x向y连边,题目即求最长链,gcd(x,m)相同的x在一个连通块内,每个连通块gcd(xi,m)向连通块gcd(xj,m)(gcd(xi,m)|gcd(xj,m))连边,得到一个边数为O(nlogn)的拓扑图,直接DP即可。

    #include<cstdio>
    #include<vector>
    #include<algorithm>
    using namespace std;
    #define ll long long
    char B[1<<26],*S=B,C;int X;
    inline int read()
    {
        while((C=*S++)<'0'||C>'9');
        for(X=C-'0';(C=*S++)>='0'&&C<='9';)X=(X<<3)+(X<<1)+C-'0';
        return X;
    }
    #define MN 200000
    int gcd(int x,int y){return y?gcd(y,x%y):x;}
    vector<int> v[MN+5];
    int m,u[MN+5],f[MN+5],r[MN+5],ls=1;
    void exgcd(ll x,ll y,ll z,ll&a,ll&b)
    {
        if(!y){a=z/x;b=0;return;}
        ll aa,bb;exgcd(y,x%y,z,aa,bb);
        a=-bb;b=-aa-bb*(x/y);
    }
    void out(int x)
    {
        if(!x)return;
        out(r[x]);
        int i;ll a,b;
        for(i=0;i<v[x].size();++i)
            exgcd(ls,m,v[x][i],a,b),
            printf("%d ",(a%m+m)%m),ls=v[x][i];
    }
    int main()
    {
        fread(B,1,1<<26,stdin);
        int n,i,j,mx=0;
        n=read();m=read();
        for(i=1;i<=n;++i)u[read()]=1;
        for(i=1;i<m;++i)if(!u[i])v[gcd(i,m)].push_back(i);
        for(i=1;i<m;++i)
        {
            if((f[i]+=v[i].size())>f[mx])mx=i;
            for(j=i;j<m;j+=i)if(f[i]>f[j])f[j]=f[i],r[j]=i;
        }
        printf("%d
    ",f[mx]+!u[0]);
        out(mx);
        if(!u[0])puts("0");
    }

    D. Varying Kibibits

    题目大意:给出n个数的集合T,F(S)的各位数字为集合S中各个数字对应位数字的最小值,例如F(123,321)=121,求的异或和。(n<=10^6,数字<=999,999)

    思路:F值恰好为x的子集不好求,我们考虑求出F值各位数字都大等x的子集,也就是数字各位都大等于x的数的集合的所有子集,答案我们枚举各位加一,容斥一下即可求出,现在问题是如何求出这个集合的子集和的平方和,只要同时维护一个集合的子集和的和、子集和的平方和、集合大小,就可以支持合并集合和删除集合(稍微推一下式子,挺简单的,或者看下面的代码),数字各位都大等于x的集合同样也可以容斥求出,总复杂度O(2^6*n),可能需要卡卡常数,正解貌似是O(6n)的,以后补。

    #include<cstdio>
    char B[1<<26],*S=B,C;int X;
    inline int read()
    {
        while((C=*S++)<'0'||C>'9');
        for(X=C-'0';(C=*S++)>='0'&&C<='9';)X=X*10+C-'0';
        return X;
    }
    #define MN 1000000
    #define MOD 1000000007
    int a[MN+5],p2[MN+5],r2[MN+5],pw[7];
    struct data
    {
        int s1,s2,sz;
        data(int s1=0,int s2=0,int sz=0):s1(s1),s2(s2),sz(sz){}
        void operator+=(const data&b)
        {
            s2=(1LL*s2*p2[b.sz]+1LL*b.s2*p2[sz]+2LL*s1*b.s1)%MOD;
            s1=(1LL*s1*p2[b.sz]+1LL*b.s1*p2[sz])%MOD;
            sz+=b.sz;
        }
        void operator-=(const data&b)
        {
            sz-=b.sz;
            s1=((s1-1LL*b.s1*p2[sz])%MOD+MOD)*r2[b.sz]%MOD;
            s2=((s2-2LL*s1*b.s1-1LL*b.s2*p2[sz])%MOD+MOD)*r2[b.sz]%MOD;
        }
    }s[MN+5];
    void solve1(int x,int k,int d,int p)
    {
        if(d>5){if(x!=k)if(p>0)s[x]+=s[k];else s[x]-=s[k];return;}
        solve1(x,k,d+1,p);
        if(k%pw[d+1]/pw[d]<9)solve1(x,k+pw[d],d+1,-p);
    }
    inline int mod(int x){if(x>=MOD)x-=MOD;if(x<0)x+=MOD;return x;}
    void solve2(int x,int k,int d,int p)
    {
        if(d>5){if(x!=k)s[x].s2=mod(s[x].s2+p*s[k].s2);return;}
        solve2(x,k,d+1,p);
        if(k%pw[d+1]/pw[d]<9)solve2(x,k+pw[d],d+1,-p);
    }
    int main()
    {
        B[fread(B,1,1<<26,stdin)]=0;
        int n=read(),i;long long ans=0;
        while(n--)++a[read()];
        for(p2[0]=i=1;i<=MN;++i)p2[i]=(p2[i-1]<<1)%MOD;
        for(r2[0]=i=1;i<=MN;++i)r2[i]=(r2[i-1]*((MOD+1LL)>>1))%MOD;
        for(pw[0]=i=1;i<7;++i)pw[i]=pw[i-1]*10;
        for(i=MN;i--;){solve1(i,i,0,-1);while(a[i]--)s[i]+=data(i,1LL*i*i%MOD,1);}
        for(i=1;i<MN;++i)solve2(i,i,0,1),ans^=1LL*i*s[i].s2;
        printf("%I64d",ans);
    }
  • 相关阅读:
    2019-12-18
    java读取XML文件,及封装XML字符串
    java不用中间变量交换两个值
    oracle获取当前月的第一个星期五
    2019-10-23
    HTTP中GET请求与POST请求的区别
    Java面试题整理(转载)
    java 字节流与字符流的区别
    20190822
    C++标准库string
  • 原文地址:https://www.cnblogs.com/ditoly/p/VK-Cup-2017-R2.html
Copyright © 2011-2022 走看看