noip2013day2题解
描述
随着智能手机的日益普及,人们对无线网的需求日益增大。某城市决定对城市内的公共场所覆盖无线网。
假设该城市的布局为由严格平行的 129 条东西向街道和 129 条南北向街道所形成的网格状,并且相邻的平行街道之间的距离都是恒定值 1 。东西向街道从北到南依次编号为0,1,2…128,南北向街道从西到东依次编号为 0,1,2…128。
东西向街道和南北向街道相交形成路口,规定编号为 x 的南北向街道和编号为 y 的东西向街道形成的路口的坐标是(x, y)。在某些路口存在一定数量的公共场所。
由于政府财政问题,只能安装一个大型无线网络发射器。该无线网络发射器的传播范围是一个以该点为中心,边长为 2*d 的正方形。传播范围包括正方形边界。
例如下图是一个 d = 1 的无线网络发射器的覆盖范围示意图。
现在政府有关部门准备安装一个传播参数为 d 的无线网络发射器,希望你帮助他们在城 市内找出合适的安装地点,使得覆盖的公共场所最多。
格式
输入格式
第一行包含一个整数 d,表示无线网络发射器的传播距离。
第二行包含一个整数 n,表示有公共场所的路口数目。
接下来 n 行,每行给出三个整数 x, y, k, 中间用一个空格隔开,分别代表路口的坐标(x, y)以及该路口公共场所的数量。同一坐标只会给出一次。
输出格式
输出一行,包含两个整数,用一个空格隔开,分别表示能覆盖最多公共场所的安装地点方案数,以及能覆盖的最多公共场所的数量。
限制
对于 100%的数据,1 ≤ d ≤ 20,1 ≤ n ≤ 20, 0 ≤ x ≤ 128, 0 ≤ y ≤ 128, 0 < k ≤ 1,000,000。
枚举每一个点
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<iostream> 5 using namespace std; 6 7 int d,n,map[25][3]; 8 long long maxsum=-1; 9 int count=0; 10 11 int main() 12 { 13 cin>>d>>n; 14 for(int i=1;i<=n;i++)cin>>map[i][0]>>map[i][1]>>map[i][2]; 15 for(int x=0;x<=128;x++) 16 for(int y=0;y<=128;y++) 17 { 18 long long sum=0; 19 for(int i=1;i<=n;i++) 20 if(x-d<=map[i][0]&&map[i][0]<=x+d 21 &&y-d<=map[i][1]&&map[i][1]<=y+d)sum+=map[i][2]; 22 if(maxsum<sum) 23 { 24 maxsum=sum; 25 count=1; 26 } 27 else if(sum==maxsum)count++; 28 } 29 cout<<count<<" "<<maxsum<<endl; 30 return 0; 31 }
描述
在有向图 G 中,每条边的长度均为 1,现给定起点和终点,请你在图中找一条从起点到 终点的路径,该路径满足以下条件:
- 路径上的所有点的出边所指向的点都直接或间接与终点连通。
- 在满足条件 1 的情况下使路径最短。
注意:图 G 中可能存在重边和自环,题目保证终点没有出边。 请你输出符合条件的路径的长度。
格式
输入格式
第一行有两个用一个空格隔开的整数 n 和 m,表示图有 n 个点和 m 条边。
接下来的 m 行每行 2 个整数 x、y,之间用一个空格隔开,表示有一条边从点 x 指向点y。
最后一行有两个用一个空格隔开的整数 s、t,表示起点为 s,终点为 t。
输出格式
输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。
如果这样的路径不存在,输出-1。
限制
对于 30%的数据,0 < n ≤ 10,0 < m ≤ 20;
对于 60%的数据,0 < n ≤ 100,0 < m ≤ 2000;
对于 100%的数据,0 < n ≤ 10,000,0 < m ≤ 200,000,0 < x,y,s,t ≤ n,x ≠ t。
提示
【输入输出样例1说明】
如上图所示,箭头表示有向道路,圆点表示城市。起点 1 与终点 3 不连通,所以满足题目描述的路径不存在,故输出-1。
【输入输出样例2说明】
如上图所示,满足条件的路径为 1->3->4->5。注意点 2 不能在答案路径中,因为点 2 连了一条边到点 6,而点 6 不与终点 5 连通。
多来次DFS即可
1 #include<stdio.h> 2 #include<cstdlib> 3 int n,m; 4 int begin[10010]; 5 int cou=0; 6 int flag[10010]; 7 int ifin[10010]; 8 int dis[10010]; 9 int getget[10010]; 10 11 struct edge 12 { 13 int b,weight,next; 14 }; 15 edge E[400010]; 16 17 int addedge(int a,int b) 18 { 19 E[cou].b=b; 20 E[cou].next=begin[a]; 21 E[cou].weight=1; 22 begin[a]=cou; 23 cou++; 24 E[cou].b=a; 25 E[cou].weight=-1; 26 E[cou].next=begin[b]; 27 begin[b]=cou; 28 cou++; 29 } 30 31 class queue 32 { 33 private: 34 int rear,front,size; 35 int q[100000]; 36 public: 37 queue() 38 { 39 rear=-1; 40 front=size=0; 41 } 42 int Dequeue() 43 { 44 int x=q[front]; 45 front++; 46 size--; 47 return x; 48 } 49 void Enqueue(int x) 50 { 51 rear++; 52 q[rear]=x; 53 size++; 54 } 55 int Getsize() 56 { 57 return size; 58 } 59 }; 60 queue mq; 61 62 void BFS1(int s) 63 { 64 mq.Enqueue(s); 65 flag[s]=1; 66 while(mq.Getsize()) 67 { 68 int now=mq.Dequeue(); 69 for(int i=begin[now];i!=-1;i=E[i].next) 70 if(E[i].weight==-1&&flag[E[i].b]==0) 71 { 72 mq.Enqueue(E[i].b); 73 flag[E[i].b]=1; 74 } 75 } 76 for(int i=1;i<=n;i++) 77 { 78 for(int j=begin[i];j!=-1;j=E[j].next) 79 if(E[j].weight==1&&flag[E[j].b]==0) 80 getget[i]=0; 81 if(flag[i]==0) 82 getget[i]=0; 83 } 84 } 85 86 int spfa(int s,int t) 87 { 88 mq.Enqueue(s); 89 ifin[s]=1; 90 dis[s]=0; 91 while(mq.Getsize()) 92 { 93 int now=mq.Dequeue(); 94 for(int i=begin[now];i!=-1;i=E[i].next) 95 if(E[i].weight==1&&E[i].weight+dis[now]<dis[E[i].b]&&getget[E[i].b]==1) 96 { 97 dis[E[i].b]=E[i].weight+dis[now]; 98 if(ifin[E[i].b]==0)mq.Enqueue(E[i].b); 99 ifin[E[i].b]=1; 100 } 101 ifin[now]=0; 102 } 103 if(dis[t]==999999999)return -1; 104 else return dis[t]; 105 } 106 107 int main() 108 { 109 int a,b; 110 scanf("%d%d",&n,&m); 111 for(int i=0;i<=n;i++) 112 begin[i]=-1,dis[i]=999999999,getget[i]=1; 113 while(m--) 114 { 115 scanf("%d%d",&a,&b); 116 addedge(a,b); 117 } 118 scanf("%d%d",&a,&b); 119 BFS1(b); 120 printf("%d\n",spfa(a,b)); 121 return 0; 122 }
描述
已知多项式方程:
a0+a1x+a2x2+...+anxn=0a0+a1x+a2x2+...+anxn=0
求这个方程在[1, m]内的整数解(n 和 m 均为正整数)。
格式
输入格式
输入共 n+2 行。
第一行包含 2 个整数 n、m,每两个整数之间用一个空格隔开。
接下来的 n+1 行每行包含一个整数,依次为a0,a1,a2,...,ana0,a1,a2,...,an
。
输出格式
第一行输出方程在[1, m]内的整数解的个数。
接下来每行一个整数,按照从小到大的顺序依次输出方程在[1, m]内的一个整数解。
限制
对于 30%的数据,0 < n ≤ 2, |ai||ai|
≤ 100,anan
≠ 0, m ≤ 100;
对于 50%的数据,0 < n ≤ 100, |ai||ai|
≤ 1010010100
,anan
≠ 0,m ≤ 100;
对于 70%的数据,0 < n ≤ 100, |ai||ai|
≤ 10100001010000
,anan
≠ 0,m ≤ 10000;
对于 100%的数据,0 < n ≤ 100, |ai||ai|
≤ 10100001010000
,anan
≠ 0,m ≤ 1000000。
秦九昭算法依赖选择的质数可以的一定包括100的分
1 #include<iostream> 2 #include<stdio.h> 3 #include<cstdlib> 4 using namespace std; 5 int pr[20]={0,20011,20021,20023,20029,20047,20051,20063,20071,20089,20101,20107,20113,20117,20123,20129,20143,20147,20149,20161}; 6 int a[20][105],b[20][30005],ans[1000005]; 7 int n,m,count; 8 9 void read(int x) 10 { 11 bool fl = 1; 12 char c = getchar(); 13 14 for(; (c < '0' || c > '9') ; c = getchar()) 15 if(c == '-') 16 fl = 0; 17 18 int ret[20]; 19 for(int i = 1 ; i <= 19 ; i++) 20 ret[i] = 0; 21 22 for(; (c >= '0' && c <= '9') ; c = getchar()) 23 for(int i = 1 ; i <= 19 ; i++) 24 ret[i] = (ret[i] * 10 + c - '0') % pr[i]; 25 26 for(int i = 1 ; i <= 19 ; i++) 27 a[i][x] = fl ? ret[i] : pr[i] - ret[i]; 28 } 29 30 void does(int x,int y) 31 { 32 int ans=0; 33 for(int i=n;i>=1;i--) 34 ans=(ans+a[x][i])*y%pr[x]; 35 ans+=a[x][0]; 36 ans%=pr[x]; 37 if(ans==0) 38 b[x][y]=1; 39 } 40 41 int main() 42 { 43 scanf("%d%d",&n,&m); 44 for(int i=0;i<=n;i++) 45 read(i); 46 for(int i=1;i<20;i++) 47 for(int j=1;j<pr[i];j++) 48 does(i,j); 49 for(int i=1;i<=m;i++) 50 { 51 int mark=1; 52 for(int j=1;j<20;j++) 53 if(b[j][i%pr[j]]==0) 54 { 55 mark=0; 56 break; 57 } 58 if(mark==1) 59 ans[i]=1,count++; 60 } 61 printf("%d\n",count); 62 for(int i=0;i<=m;i++) 63 if(ans[i]==1) 64 printf("%d\n",i); 65 return 0; 66 }