T1无线网络发射选址
题目链接:http://codevs.cn/problem/3730/
题解:
直接枚举安装地点即可。
代码:
#include<iostream>
#include<cstdio>
using namespace std;
int n,m,d,x,y,sum;
long long a[300][300],maxx,z;
int main(){
scanf("%d%d",&d,&n);
for (int i=1;i<=n;i++){
scanf("%d%d%lld",&x,&y,&z);a[x][y]=z;
}
for (int i=0;i<=128;i++)
for (int j=0;j<=128;j++){
long long temp(0);
for (int k=max(0,i-d);k<=min(i+d,128);k++)
for (int p=max(0,j-d);p<=min(j+d,128);p++)
temp+=a[k][p];
if (temp>maxx){maxx=temp;sum=1;}
else if (temp==maxx)sum++;
}
cout<<sum<<' '<<maxx<<endl;
}
T2寻找道路
题目链接:http://codevs.cn/problem/3731/
题解:
先建一个反图。从终点dfs一遍,处理出哪些点可以到终点。
判断一下哪些点可能出现在最短路中。
然后在原图中跑一遍bfs即可。
代码:
#include<iostream>
#include<cstdio>
#define N 10010
#define M 200010
using namespace std;
struct use{int st,en;}e[M],ef[M];
int point[N],l[N*10],pointf[N],next[M],nextf[M],cnt,x,y,n,m,s,t,dis[N];
bool vis[N],pass[N],f[N];
void add(int x,int y){
next[++cnt]=point[x];point[x]=cnt;e[cnt].st=x;e[cnt].en=y;
nextf[cnt]=pointf[y],pointf[y]=cnt;ef[cnt].st=y;ef[cnt].en=x;
}
void dfs(int x){
for (int i=pointf[x];i;i=nextf[i])
if (!vis[ef[i].en]){vis[ef[i].en]=1;dfs(ef[i].en);}
}
void bfs(int x){
int h=0,ti=1;l[ti]=x;f[x]=true;
while(h<ti){
int u=l[++h];if (u==t) break;
for (int i=point[u];i;i=next[i])
if (pass[e[i].en]&&!f[e[i].en]){
l[++ti]=e[i].en;dis[e[i].en]=dis[u]+1;f[e[i].en]=1;
}
}
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++){scanf("%d%d",&x,&y);add(x,y);}
scanf("%d%d",&s,&t);vis[t]=1;dfs(t);
for (int i=1;i<=n;i++){
bool f(true);
for (int j=point[i];j;j=next[j]) if (!vis[e[j].en]){f=false;break;}
if (f) pass[i]=true;
}
bfs(s);cout<<dis[t]<<endl;
}
T3解方程
题目链接:http://codevs.cn/problem/3732/
题解:
这应该是这次noip中最难的一道题了。
首先有两个性质.若f(x)=0(mod p)则f(x+p)=0(mod p);
若原方程成立。那么在方程两边同时模P,方程仍然成立。
所以我们可以选几个大质数,首先预处理出1-(P-1)代入方程在模P意义下的结果。
然后我们枚举解。每次用这几个大质数检验一下即可。
这样出错的概率非常低。。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define M 1000010
#define N 10010
using namespace std;
int p[5]={11261,23333,10007,21893,14843};
int ans[M],a[5][N],t[5][200],len,c[5][50010],n,m;
char ch[N];
int cal(int tt){
int temp(0);
for (int i=0;i<=n;i++) (temp+=a[tt][i]*t[tt][i])%=p[tt];
if (temp<0) temp+=p[tt];
return temp;
}
bool check(int x){
for (int i=0;i<5;i++) if(c[i][x%p[i]]!=0) return false;
return true;
}
int main(){
scanf("%d%d",&n,&m);
for (int i=0;i<=n;i++){
scanf("%s",ch+1);int f(1);len=strlen(ch+1);
for (int j=0;j<5;j++){
if (ch[1]!='-') a[j][i]=ch[1]-'0';else f=0;
for (int k=2;k<=len;k++) (a[j][i]=a[j][i]*10+ch[k]-'0')%=p[j];
if (!f) a[j][i]=-a[j][i];
}
}
for (int i=0;i<5;i++)
for (int j=1;j<p[i];j++){
t[i][0]=1;for(int k=1;k<=n;k++) (t[i][k]=t[i][k-1]*j)%=p[i];
c[i][j]=cal(i);
}
for (int i=1;i<=m;i++) if (check(i)) ans[++ans[0]]=i;cout<<ans[0]<<endl;
for (int i=1;i<=ans[0];i++) cout<<ans[i]<<endl;
}