1.无线网络发射器选址
题目::https://www.luogu.org/problem/show?pid=2038
题解::第一题水题,直接枚举放的位置,用二维前缀和维护一下,注意一下边界就行了。时间复杂度O(129^2);
代码::
#include<cstdio> #include<algorithm> using namespace std; template<class T>inline void read(T &x) { x=0;int f=0;char ch=getchar(); while(ch<‘0‘||ch>‘9‘)f|=(ch==‘-‘),ch=getchar(); while(ch<=‘9‘&&ch>=‘0‘)x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); x=f?-x:x; return; } int sum[200][200],num[200][200]; int main() { int d,n,x,y,k,t=0,ans=0; read(d);read(n); for(int i=1;i<=n;i++) { read(x);read(y);read(k); num[x+1][y+1]=k; } for(int i=1;i<=129;i++) for(int j=1;j<=129;j++) sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+num[i][j]; for(int i=1;i<=129;i++) for(int j=1;j<=129;j++) { int x1=min(129,i+d),y1=min(129,j+d),x2=max(0,i-d-1),y2=max(0,j-d-1); if(sum[x1][y1]+sum[x2][y2]-sum[x1][y2]-sum[x2][y1]>ans) { ans=sum[x1][y1]+sum[x2][y2]-sum[x1][y2]-sum[x2][y1]; t=1; } else if(sum[x1][y1]+sum[x2][y2]-sum[x1][y2]-sum[x2][y1]==ans)t++; } printf("%d %d\n",t,ans); return 0; }
2.寻找道路
题目::https://www.luogu.org/problem/show?pid=2296
题解::先反向建边bfs求出所有与终点不联通的点,在枚举每个点的每条边的终点是否联通,判断出可以在路径上的点,最后跑一边最短路就可以了;
代码::
#include<cstdio> #include<cstring> #include<algorithm> #define maxn 10010 #define inf 2000000010 using namespace std; template<class T>inline void read(T &x) { x=0;int f=0;char ch=getchar(); while(ch<‘0‘||ch>‘9‘)f|=(ch==‘-‘),ch=getchar(); while(ch<=‘9‘&&ch>=‘0‘)x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); x=f?-x:x; return; } struct node{int v,next;}e[200100],E[200100]; int cnt,head[maxn],Head[maxn],d[maxn],q[1000100],n,m; bool vis[maxn],can[maxn]; void ins(int u,int v){e[++cnt].v=v;e[cnt].next=head[u];head[u]=cnt;} void Ins(int u,int v){E[cnt].v=v;E[cnt].next=Head[u];Head[u]=cnt;} void bfs(int s) { vis[s]=true; int h=0,t=0;q[0]=s; while(h<=t) { int u=q[h++]; for(int p=Head[u];p;p=E[p].next) { int v=E[p].v; if(!vis[v])q[++t]=v,vis[v]=true; } } } void init() { memset(can,true,sizeof(can)); for(int i=1;i<=n;i++) if(!vis[i])can[i]=false; else for(int p=head[i];p;p=e[p].next) { int v=e[p].v; if(!vis[v])can[i]=false; } } int spfa(int s,int T) { memset(vis,false,sizeof(vis)); memset(d,0x7f,sizeof(d)); d[s]=0;vis[s]=true;q[0]=s; int h=0,t=0; while(h<=t) { int u=q[h++]; for(int p=head[u];p;p=e[p].next) { int v=e[p].v; if(!can[v])continue; if(d[v]>d[u]+1) { d[v]=d[u]+1; if(!vis[v])vis[v]=true,q[++t]=v; } } vis[u]=false; } if(d[T]>inf)return -1; else return d[T]; } int main() { int x,y,s,t; read(n);read(m); for(int i=1;i<=m;i++) { read(x);read(y);ins(x,y);Ins(y,x); } read(s);read(t); bfs(t); init(); if(!can[s])printf("-1\n"); else printf("%d\n",spfa(s,t)); return 0; }
3.解方程
题目::https://www.luogu.org/problem/show?pid=2312
题解::如果直接按照题目模拟,不仅时间复杂度上很难接受,而且要打高精度乘和高精度加,代码复杂度很大。那么我们该怎么办呢?我们可以想到如果一个数为0,那么这个数对任意一个数取余也为0,反过来却不一定,所以我们对这个数对很多的质数取余,
如果都为0,那么这个数就是0,这些质数怎么选呢?我们选3到4个质数使他们的乘积大于m的最大值即可。这样做是O(nmk)k是质数的个数,这样是70分的。那么怎么办?
如果有一个数x,他对一个质数p取余为y,那么x+p对p取余也为y,所以我们不需要枚举m个数,只需要枚举p-1个数(p是我们选的质数),这样就可以过了。
tips:读入时,我们一位一位的读,同时取余,这样就不需要高精度了。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; long long a[110][6]; char s; int ans[1000010],f[31010][3],cnt,n,m,mod[6]={10007,10917,30071}; void read(int x) { long long ret=0,F=0,cnt=0; char ch=s; while(ch<‘0‘||ch>‘9‘) { if(ch==‘-‘)F=1; ch=getchar(); } while(ch>=‘0‘&&ch<=‘9‘) { for(int i=0;i<3;i++)a[x][i]=(a[x][i]*10+ch-‘0‘)%mod[i]; ch=getchar(); } if(F)for(int i=0;i<3;i++)a[x][i]=mod[i]-a[x][i]; } bool solve(long long x,int op) { long long sum=0; for(int i=n;i>=0;i--)sum=(a[i][op]+sum*x)%mod[op]; return !sum; } int main() { scanf("%d%d",&n,&m); for(int i=0;i<=n;i++)read(i); for(int i=0;i<3;i++) for(int j=0;j<mod[i];j++) f[j][i]=solve(j,i); for(int i=1;i<=m;i++) if(f[i%mod[0]][0]&&f[i%mod[1]][1]&&f[i%mod[2]][2])ans[++cnt]=i; printf("%d\n",cnt); for(int i=1;i<=cnt;i++)printf("%d\n",ans[i]); return 0; }
测试成绩:
总分240
第一题:70
第二题:100
第三题:70
总结:
第一题打二维前缀和时,边界判断错误,失掉了30分,这是不应该的,第一题失分说明自己对第一题的重视不够,太大意了,下次要记住教训。
第二题思路比较清晰,打的也比较快,这也归功于平常的图论刷的比较多。别的类型的题刷的还是少了。
第三题想的比较久,打的比较久,成绩也还行,差一点就想到正解了,数学题还是比较难,也没什么办法……
这次测试总的来说做的还行,希望能继续保持下去。
原文:http://www.cnblogs.com/jiangtao0508/p/7719797.html