丧病出题人。我提答搜索顺序写反了,交完才发现,改完完爆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 ",ans); }
T3.Anivia 的最大独立集
题目大意:提交答案题,给一张图,求最大独立子集。
思路:第1~4个点是小数据点,随便暴力都能过。5号点是完全图,随便输出一个点。6~7是二分图,可以网络流一下。8~10是n=1000的随机点,随便dfs+最优性剪枝就能搜到比较优的解。我后三个点的搜索顺序写反了,结果程序效率感人,得分79/100。