Codeforces Round #432 (Div. 2)题解

A.Arpa and a research in Mexican wave

简单模拟题,略

B.Arpa and an exam about geometry

题意:

已知三个点的坐标,能否找到一个点和一个角度,使得整个坐标系绕这个点旋转这个角度之后A到B的位置,B到C的位置

思路:

首先如果三个点共线显然无解,否则它们构成一个三角形,找到这个三角形的外心,记做O,如果角AOB=角BOC则存在,反之不存在,考虑到角的比等于边的比,直接判断AB是否等于BC就行了

AC代码:

#include <bits/stdc++.h>
using namespace std;
long long x1,y1,x2,y2,x3,y3;
int main()
{
    scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&x1,&y1,&x2,&y2,&x3,&y3);
    long long dx1=x2-x1,dx2=x3-x2,dx3=x3-x1;
    long long dy1=y2-y1,dy2=y3-y2,dy3=y3-y1;
    if(dx1*dy3==dx3*dy1)
        printf("No\n");
    else
    {
        long long dist1=dx1*dx1+dy1*dy1;
        long long dist2=dx2*dx2+dy2*dy2;
        long long dist3=dx3*dx3+dy3*dy3;
        if (dist1==dist2)
            printf("Yes\n");
        else
            printf("No\n");
    }
}

C.Five Dimensional Points

题意:

在五维超空间下有若干个点,对于一个点\(a\)如果存在\(b、c\)使得角\(bac\)为锐角,那么称这个角是坏的,反之则是好的,给定若干个点,输出有多少个好点以及它们的编号

\(n \le 1000\)

思路:

暴力做的话复杂度\(O(n^3)\)

但是事实上,如果点数大于\(33\)一定不存在好点,证明:

将任意一个点作为\(a\)点转换为坐标原点,那么其他点的坐标正负的情况共有\(2^5=32\)种,如果点数大于\(32\)的话由容斥原理,一定存在两个点,设为\(b、c\)坐标的正负情况完全相同,那么考虑内积角\(bac\)一定为锐角

(官方题解说大于$2 \times $维数的话一定不存在,没有证明,直接类比推理……,我也不会证……)

所以大于\(33\)的情况直接输出0,否则暴力做就可以了

(然而,数据水,直接暴力做就能过了!!?,虽说感觉的确不好构造数据卡掉)

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e3+7;
int dot[maxn][maxn];
int a[maxn],b[maxn],c[maxn],d[maxn],e[maxn];
int len[maxn];
vector <int> good;
int n;
bool flag=false;
bool check(int i)
{
    for (int j=0;j<n;j++)
        for (int k=0;k<n;k++)
        {
            if(j==i||k==i||j==k)  continue;
            if((a[j]-a[i])*(a[k]-a[i])+(b[j]-b[i])*(b[k]-b[i])+(c[j]-c[i])*(c[k]-c[i])+(d[j]-d[i])*(d[k]-d[i])+(e[j]-e[i])*(e[k]-e[i])>0)
            {
                //cout<<j<<" "<<k<<endl;
                return true;
            }
        }
    return false;
}
int main()
{
    scanf("%d",&n);
    for (int i=0;i<n;i++)
        scanf("%d%d%d%d%d",&a[i],&b[i],&c[i],&d[i],&e[i]);
    if(n>50)
    {
        printf("0\n");
        return 0;
    }
    for (int i=0;i<n;i++)
        if(!check(i))   good.push_back(i+1);
    printf("%d\n",good.size());
    for (int i=0;i<good.size();i++)
        printf("%d\n",good[i]);
}

D. Arpa and a list of numbers

题意

给定一个序列a,我们可以对序列中的元素做一下两种操作:

(1)花费\(x\)删除这个元素

(2)花费\(y\)将这个元素\(+1\)

输出使得整个序列的\(gcd\)不为\(1\)的最小花费

\(n \le 5e5\) \(a_i \le 1e6\)

思路:

首先显然可以只考虑\(gcd\)是素数的情况,如果给定一个\(gcd\),那么我们可以在\(O(n)\)的时间内求出最小的花费,然而数据范围内大概有\(70000\)个素数,不能枚举

进而考虑一次处理一段区间,对于一个区间$ [k \times gcd , (k+1) \times gcd -1)]$ ,越接近右端点提升这个数到\((k+1) \times gcd\) 所需的花费越小,所以越靠近左侧删除越划算,越靠近右侧增加越划算,可以找到一个界,使得左侧都是删除,右侧都是增加,那么预处理后我们就可以\(O(1)\)地算出一个区间的花费了

推导后可以算出这个界是$ mid =k+ gcd- min (\frac{x}{y}-1,gcd)$ ,那么对于一段区间,代价是:

左端点到\(mid\)的数量 $\times x + \sum mid $到右端点 \((\)右端点\(-a_i) \times y\)

\(cnt_{ij}\)\(i\)\(j\)的元素数,\(sum_{ij}\) 为值为\(i\)\(j\)的元素之和,转化为

\[cnt_{i,mid} \times x + (cnt_{mid,r} \times r - sum_{mid,r}) \times y \]

用前缀和预处理\(cnt\)\(sum\)即可

时间复杂度

$ O(n \sum \frac{1}{p}) = O(nloglogn)$ (Mertens' theorems)

AC代码

#include <bits/stdc++.h>
using namespace std;
const int maxn=5e5+7;
const int maxm=1e6+10;
int x,y,n;
int a[maxn],prime[maxm],cnt[maxm*2];
long long sum[maxm*2];
int tot=0,amax=0;
bool vis[maxm];
void init()
{
    int m=(int)sqrt(1e6+0.5);
    memset(vis,0,sizeof(vis));
    for (int i=2;i<=m;i++)
        if(!vis[i])
            for (int j=i*i;j<=1e6;j+=i) vis[j]=true;
    for (int i=2;i<=1e6;i++)    if(!vis[i]) prime[++tot]=i;
    for (int i=0;i<=2e6;i++)
        cnt[i]+=cnt[i-1],sum[i]+=sum[i-1];
}
int main()
{
    scanf("%d%d%d",&n,&x,&y);
    for (int i=0;i<n;i++)   scanf("%d",&a[i]),cnt[a[i]]++,sum[a[i]]+=a[i],amax=max(amax,a[i]);
    init();
    long long ans=0x3f3f3f3f3f3f3f3fll;
    for (int j=1;j<=tot;j++)
    {
        int gcd=prime[j];
        long long ret=0;
        int mid=gcd-min(x/y+1,gcd);
        for (int i=0;i<amax;i+=gcd)
        {
            int p=i+gcd;
            ret+=(long long)x*(cnt[i+mid]-cnt[i]);
            ret+=(1ll*(cnt[p]-cnt[i+mid])*p-(sum[p]-sum[i+mid]))*y*1ll;
        }
        ans=min(ret,ans);
    }
    printf("%I64d\n",ans);
}

posted @ 2017-09-05 22:33  阿瓦隆的精灵  阅读(208)  评论(0编辑  收藏  举报