【noip2014提高组】【Day2】【解题报告】

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;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值