AmazingCounters.com

2017-3-2校内训练

丧病出题人。我提答搜索顺序写反了,交完才发现,改完完爆std……219/300

 

T1.Anivia 的几何题

题目大意:给定w个正方形的两个对角坐标,求横坐标0~n-1,纵坐标0~m-1内各整点是否被矩形覆盖。(1<=n,m<=100,w<=10,坐标均为整数且在[-100,200]内)

思路:出题人为了“让初中学弟也能做出来”出的题。根据两个对角点可以算出正方形其他顶点的坐标,每个整点枚举矩形算下叉积就可以了。可以把所有坐标乘以2,这样所有运算都是整数,可以避免实数类型一些不必要的麻烦。

#include<cstdio>
#define MN 10
struct P{int x,y;P(int x=0,int y=0):x(x),y(y){}}p[4][MN+5];
P operator-(P a,P b){return P(a.x-b.x,a.y-b.y);}
int operator*(P a,P b){return a.x*b.y-a.y*b.x;}
int cal(P a,P b,P c){return (b-a)*(c-a);}
int main()
{
    int n,m,w,i,j,k,px,py;
    scanf("%d%d%d",&n,&m,&w);
    for(i=0;i<w;++i)
    {
        scanf("%d%d%d%d",&p[0][i].x,&p[0][i].y,&p[2][i].x,&p[2][i].y);
        p[0][i].x*=2;p[0][i].y*=2;p[2][i].x*=2;p[2][i].y*=2;
        px=(p[0][i].x+p[2][i].x)/2;py=(p[0][i].y+p[2][i].y)/2;
        p[1][i].x=px+py-p[0][i].y;p[1][i].y=py-px+p[0][i].x;
        p[3][i].x=px-py+p[0][i].y;p[3][i].y=py+px-p[0][i].x;
    }
    for(i=0;i<n;++i,puts(""))for(j=0;j<m;++j,putchar(k<w?'#':'.'))for(k=0;k<w;++k)
    {
        P x(i<<1,j<<1);int a,b,c,d;
        a=cal(p[0][k],p[1][k],x);b=cal(p[1][k],p[2][k],x);
        c=cal(p[2][k],p[3][k],x);d=cal(p[3][k],p[0][k],x);
        if((!a||!c||(a<0^c>0))&&(!b||!d||(b<0^d>0)))break;    
    }
}

 

T2.Anivia 的质数

题目大意:求[l,r]内有多少个各位数字都是质数的质数。(1<=l<=r<=10^15,r-l<=10^9)

思路:一位数的质数只有2,3,5,7,[l,r]内的各位都是质数的数字数量实际上只有约4^9个,搜索出来,用预处理出的素数表暴力判断素数就有40分了(我的做法)。出题人给的正解是拿预处理出的素数暴力去[l,r]里筛,可以分段筛避免爆空间。我不知道1s是怎么筛10亿的,复杂度O(能过)。

40/100(假装A了)

#include<cstdio>
#define ll long long
#define MX 33333360
#define MP 2051000
const int o[5]={0,2,3,5,7};
int l[20],r[20],p[20],ans,pr[MP+5],pn,f[MX/30+5];
bool check(ll x)
{
    for(int i=1;(ll)pr[i]*pr[i]<=x;++i)
        if(x%pr[i]==0)return false;
    return true;
}
void dfs(int x,int a,int b,int c)
{
    if(x<0)
    {
        ll x=0;
        for(int i=15;i--;)x=x*10+p[i];
        if(check(x))++ans;
        return;
    }
    for(int i=0;i<5;++i)
        if((!a||i)&&(b||o[i]>=l[x])&&(c||o[i]<=r[x]))
            p[x]=o[i],dfs(x-1,a||o[i],b||o[i]>l[x],c||o[i]<r[x]);
}
int get(int p){return f[p/30]&(1<<p);}
void fill(int p){f[p/30]|=(1<<p);}
int main()
{
    ll x;int i,j;
    for(i=2;i<=MX;++i)
    {
        if(!get(i))pr[++pn]=i;
        for(j=1;i*pr[j]<=MX;++j){fill(i*pr[j]);if(i%pr[j]==0)break;}
    }
    scanf("%I64d",&x);for(i=0;x;x/=10)l[i++]=x%10;
    scanf("%I64d",&x);for(i=0;x;x/=10)r[i++]=x%10;
    dfs(15,0,0,0);
    printf("%d\n",ans);
}

 

T3.Anivia 的最大独立集

题目大意:提交答案题,给一张图,求最大独立子集。

思路:第1~4个点是小数据点,随便暴力都能过。5号点是完全图,随便输出一个点。6~7是二分图,可以网络流一下。8~10是n=1000的随机点,随便dfs+最优性剪枝就能搜到比较优的解。我后三个点的搜索顺序写反了,结果程序效率感人,得分79/100。

posted on 2017-03-02 20:50  ditoly  阅读(143)  评论(0编辑  收藏  举报