标签:
好吧,15年写14年题解,的确够晚的(P.S. 是因为我到现在才搞懂这些题)
正文之前,先膜拜膜拜一位大爷 %%% _debug
多膜拜膜拜 _debug 大爷,打程序时bug会减少哦
传送门:
生活大爆炸版石头剪刀布: http://codevs.cn/problem/3716/
联合权值: http://codevs.cn/problem/3728/
飞扬的小鸟: http://codevs.cn/problem/3729/
无线网络发射器选址: http://codevs.cn/problem/3578/
寻找道路: http://codevs.cn/problem/3731/
解方程: http://codevs.cn/problem/3732/
这里讲题的顺序:由易到难
Day1 T1 与 Day2 T1
这两题若是不会做,建议你先搜搜A+B problem的题解
直接上代码了
P.S. 代码是pascal的 这是我14年考试时的代码 14年我不会用C (QAQ)
Day1 T1
1 var 2 n,na,nb,i,j,win1,win2,ls1,ls2:longint; 3 a,b:array[0..200]of longint; 4 p:array[0..4,0..4]of 0..2; 5 begin 6 readln(n,na,nb); 7 for i:=1 to na do read(a[i]); 8 for i:=1 to nb do read(b[i]); 9 p[0,0]:=0; p[0,1]:=2; p[0,2]:=1; p[0,3]:=1; p[0,4]:=2; 10 p[1,0]:=1; p[1,1]:=0; p[1,2]:=2; p[1,3]:=1; p[1,4]:=2; 11 p[2,0]:=2; p[2,1]:=1; p[2,2]:=0; p[2,3]:=2; p[2,4]:=1; 12 p[3,0]:=2; p[3,1]:=2; p[3,2]:=1; p[3,3]:=0; p[3,4]:=1; 13 p[4,0]:=1; p[4,1]:=1; p[4,2]:=2; p[4,3]:=2; p[4,4]:=0; 14 win1:=0; win2:=0; 15 for i:=1 to n do 16 begin 17 ls1:=a[(i-1) mod na+1]; 18 ls2:=b[(i-1) mod nb+1]; 19 if p[ls1,ls2]=1 then inc(win1); 20 if p[ls1,ls2]=2 then inc(win2); 21 end; 22 writeln(win1,‘ ‘,win2); 23 end.
Day2 T1
1 var 2 i,j,l,n,d,ans,x,y,k,ans1,ans2,max1,max2,left,right,up,down:longint; 3 sum:array[-1..128,-1..128]of longint; 4 function min(a,b:longint):longint; 5 begin 6 if a<b then exit(a) else exit(b); 7 end; 8 function max(a,b:longint):longint; 9 begin 10 if a>b then exit(a) else exit(b); 11 end; 12 begin 13 readln(d); readln(n); max1:=0; max2:=0; 14 for i:=1 to n do 15 begin 16 readln(x,y,k); 17 max1:=max(x,max1); 18 max2:=max(y,max2); 19 for j:=x to 128 do 20 for l:=y to 128 do 21 inc(sum[j,l],k); 22 end; 23 for i:=0 to min(128,max1+2*d) do 24 for j:=0 to min(128,max2+2*d) do 25 begin 26 up:=max(0,i-d); 27 down:=min(128,i+d); 28 left:=max(0,j-d); 29 right:=min(128,j+d); 30 l:=sum[down,right]-sum[down,left-1]-sum[up-1,right]+sum[up-1,left-1]; 31 if l>ans2 then begin ans1:=1; ans2:=l; end 32 else if l=ans2 then inc(ans1); 33 end; 34 writeln(ans1,‘ ‘,ans2); 35 end.
Day1 T2 联合权值
记录每个点的儿子节点权值的 和(sum[])、最大值(max1[])、次大值(max2[])
令数组w[]记录每个点的权值
令ans1记录联合权值最大值,ans2记录联合权值和
以1为树的根,全部BFS一遍,在BFS中
对于每一次搜到的点 u
ans1=max(ans1,max1[u]*max2[u])
对于每一次搜到的边 u--->v
ans1=max(ans1,w[u]*max1[v])
ans2+=w[v]*(sum[u]-w[v])
ans2+=w[u]*sum[v]*2
大概就是这样了
代码如下
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 using namespace std; 6 #define LL long long 7 const int maxn=200000+10; 8 int n,m,i,j,w[maxn],sum[maxn],max1[maxn],max2[maxn]; 9 int aa[maxn],bb[maxn],ans1,ans2; 10 struct node{ 11 int v; 12 node *next; 13 }; 14 node *g[maxn],*p; 15 void add(int u,int v) 16 { 17 p=new(node); 18 p->v=v; 19 p->next=g[u]; 20 g[u]=p; 21 } 22 int dui[maxn],h,t; 23 int max(int a,int b) {return a>b?a:b;} 24 int min(int a,int b) {return a<b?a:b;} 25 int main() 26 { 27 scanf("%d",&n); 28 for (i=1;i<n;i++) 29 { 30 int a,b; 31 scanf("%d%d",&a,&b); 32 if (a>b) {int t=a;a=b;b=t;} 33 add(a,b); 34 aa[i]=a; bb[i]=b; 35 } 36 for (i=1;i<=n;i++) scanf("%d",&w[i]); 37 for (i=1;i<n;i++) 38 { 39 int a=aa[i],b=bb[i]; 40 sum[a]+=w[b]; 41 sum[a]%=10007; 42 if (w[b]>=max1[a]) max2[a]=max1[a],max1[a]=w[b]; 43 else max2[a]=max(max2[a],w[b]); 44 } 45 h=0; t=1; dui[1]=1; 46 while (h!=t) 47 { 48 h++; 49 int u=dui[h]; 50 ans1=max(ans1,max2[u]*max1[u]); 51 p=g[u]; 52 while (p!=NULL) 53 { 54 dui[++t]=p->v; 55 int v=p->v; 56 ans1=max(ans1,w[u]*max1[v]); 57 ans2+=w[v]*(sum[u]-w[v]); 58 ans2+=w[u]*sum[v]*2; 59 ans2%=10007; 60 p=p->next; 61 } 62 } 63 ans2%=10007; 64 printf("%d %d\n",ans1,ans2); 65 }
记得ans2要对10007取模
Day2 T2寻找道路
傻B题
思路大概是,先把所有边反向,从终点来一次DFS/BFS,标记所有经过了的点
然后会有一些没标记的点,这些就是走不到终点的
在原图上,把指向走不到终点的点的点删掉(这句话有点绕,多绕绕就会绕了)
再从起点来一遍SPFA
好吧,就这么简单
P.S. 去年在考场上时是想到了这个方法的,可惜邻接表不会打,打了个邻接矩阵,70分 (QAQ)
废话不多说,代码如下
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 using namespace std; 6 #define LL long long 7 const int maxn=10000+10; 8 const int INF=10000000; 9 int n,m,i,j,a[maxn],S,T,dis[maxn]; 10 int Q[maxn],h,t; 11 int max(int a,int b) {return a>b?a:b;} 12 int min(int a,int b) {return a<b?a:b;} 13 struct node{ 14 int v; 15 node *next; 16 }; 17 node *g[maxn],*g2[maxn],*p; 18 bool in[maxn]; 19 node *add(int u,int v,node *nd) 20 { 21 node *p; 22 p=new(node); 23 p->v=v; 24 p->next=nd; 25 return p; 26 } 27 void spfa() 28 { 29 int i,j; 30 node *p; 31 for (i=0;i<=n;i++) dis[i]=INF,in[i]=0; 32 h=0; t=1; dis[S]=0; in[S]=0; Q[1]=S; 33 while (h!=t) 34 { 35 h++; 36 int u=Q[h]; 37 p=g[u]; 38 while (p!=NULL) 39 { 40 int v=p->v; 41 if (dis[u]+1<dis[v]) 42 { 43 dis[v]=dis[u]+1; 44 if (!in[v]) Q[++t]=v,in[v]=1; 45 } 46 p=p->next; 47 } 48 in[u]=0; 49 } 50 } 51 int main() 52 { 53 scanf("%d%d",&n,&m); 54 for (i=1;i<=m;i++) 55 { 56 int a,b; 57 scanf("%d%d",&a,&b); 58 g[a]=add(a,b,g[a]); 59 g2[b]=add(b,a,g2[b]); 60 } 61 scanf("%d%d",&S,&T); 62 h=0; t=1; Q[1]=T; in[T]=1; 63 while (h!=t) 64 { 65 h++; 66 int u=Q[h]; 67 p=g2[u]; 68 while (p!=NULL) 69 { 70 if (!in[p->v]) Q[++t]=p->v,in[p->v]=1; 71 p=p->next; 72 } 73 } 74 if (!in[S]) {printf("-1\n"); return 0;} 75 for (i=1;i<=n;i++) 76 if (!in[i]) 77 { 78 p=g2[i]; 79 while (p!=NULL) 80 { 81 if (p->v==S) {printf("-1\n"); return 0;} 82 g[p->v]=NULL; 83 p=p->next; 84 } 85 } 86 spfa(); 87 if (dis[T]==INF) {printf("-1\n"); return 0;} 88 printf("%d\n",dis[T]); 89 }
Day1 T3 飞扬的小鸟
P.S. 每次看到“飞扬的小鸟”我就觉得我是手残
大爷一眼就能看出要用DP做,唯我第一想法是暴搜
dp[i][j]——小鸟飞到 第i列 高度为j的地方时,最少点击次数
令数组U[i]记录在第i-1列点击一次上升的高度
数组D[i]记录在第i-1列不点击下降的高度
边界条件:dp[0][0]=INF ; dp[0][j]=0 (j=1...m)
转移方程:
1)上升 dp[i][j]=min(dp[i][j],dp[i][j-U[i]]+1,dp[i-1][j-U[i]]+1);
2)下降 dp[i][j]=min(dp[i][j],dp[i-1][j+D[i]]);
3)j=m要特判
这一题更加详细的题解我会在以后写出
请关注我的博客http://www.cnblogs.com/Donnie-Darko/
(P.S. 其实现在我的博客里也没什么东西,上面那句话本身想删了的,可是再想一想又觉得,脸皮还是厚点好)
代码如下
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 using namespace std; 6 #define LL long long 7 const int maxn=10000+10; 8 const int maxm=1000+10; 9 const int INF=100000; 10 int n,m,i,j,k,dp[maxn][maxm],U[maxn],D[maxn],ans=0; 11 bool pass[maxn][maxm],conduit[maxn]; 12 int max(int a,int b) {return a>b?a:b;} 13 int min(int a,int b) {return a<b?a:b;} 14 int main() 15 { 16 scanf("%d%d%d",&n,&m,&k); 17 for (i=0;i<=n;i++) pass[i][0]=1; 18 for (i=1;i<=n;i++) 19 scanf("%d%d",&U[i],&D[i]); 20 for (i=1;i<=k;i++) 21 { 22 int a,b,c; 23 scanf("%d%d%d",&a,&b,&c); 24 conduit[a]=1; 25 for (j=0;j<=b;j++) pass[a][j]=1; 26 for (j=c;j<=m;j++) pass[a][j]=1; 27 } 28 dp[0][0]=INF; 29 for (i=1;i<=n;i++) 30 { 31 for (j=0;j<=m;j++) dp[i][j]=INF; 32 for (j=U[i]+1;j<m;j++) 33 { 34 dp[i][j]=min(dp[i][j],dp[i][j-U[i]]+1); 35 dp[i][j]=min(dp[i][j],dp[i-1][j-U[i]]+1); 36 } 37 for (j=0;j<=m-D[i];j++) 38 dp[i][j]=min(dp[i][j],dp[i-1][j+D[i]]); 39 for (int o=1;o<=m;o++) 40 { 41 int p=(m-o)/U[i]; 42 if ((m-o)%U[i]!=0||p==0) p++; 43 dp[i][m]=min(dp[i][m],dp[i-1][o]+p); 44 } 45 int minl=INF; 46 for (j=0;j<=m;j++) if (pass[i][j]) dp[i][j]=INF; 47 for (j=0;j<=m;j++) minl=min(minl,dp[i][j]); 48 if (minl==INF) break; 49 if (conduit[i]) ans++; 50 } 51 if (ans<k) printf("0\n%d\n",ans); 52 else 53 { 54 ans=INF; 55 for (i=1;i<=m;i++) ans=min(ans,dp[n][i]); 56 printf("1\n%d\n",ans); 57 } 58 }
Day2 T3 解方程
每次看到这种数学题就想弃疗
这题,要用模糊一点的方法做
也就是枚举x,算答案时不停对10007取模,若最后的答案是0,就当成正确答案了(连long long都不要用)
当然,天知道出数据的人会不会整个变态数据卡10007
所以我准备了5个模数{11261,19997,22877,21893,14843},只有答案全为0,才认为是正确答案
你来卡我啊,卡我啊,我看你怎么卡
于是这题就愉快的AC了
等等,细心的同学发现了,这样会超时,唉,上面那句话当我没说好了
大家可以发现,在模p意义下
如果x0不是答案
那么在模p意义下,x0+p不是答案,x0+2p也不是答案......
时间复杂度瞬间下降对不对
还是那句话,这一题更加详细的题解我会在以后写出
请关注我的博客http://www.cnblogs.com/Donnie-Darko/
(P.S. 记得电视上的广告脸皮厚到能连播三遍,我说两遍又有什么错)
代码如下
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 using namespace std; 6 char s[10010]; 7 int n,m,i,j,a[5][1000010]; 8 bool ok[5][1000010]; 9 int mod[5]={11261,19997,22877,21893,14843}; 10 bool pass(char c){return ((‘0‘<=c&&c<=‘9‘)||c==‘-‘);} 11 int ans[1000010]; 12 int min(int a,int b) {return a<b?a:b;} 13 bool jud(int x) 14 { 15 for(int t=0;t<5;t++) 16 if(ok[t][x%mod[t]]!=0)return 0; 17 return 1; 18 } 19 void R(int p) 20 { 21 scanf("%s",s+1); 22 int len=strlen(s+1); 23 bool flag=0; 24 for (int t=0;t<5;t++) 25 if(s[1]!=‘-‘) a[t][i]=s[1]-‘0‘; 26 else a[t][i]=0,flag=1; 27 for (int t=0;t<5;t++) 28 { 29 for (int k=2;k<=len;k++) 30 a[t][i]=(a[t][i]*10+s[k]-‘0‘)%mod[t]; 31 if (flag) a[t][i]=-a[t][i]; 32 } 33 } 34 int main() 35 { 36 scanf("%d%d",&n,&m); 37 for (i=0;i<=n;i++) R(i); 38 int pre[5][110],res[5]; 39 for (i=0;i<=4;i++) pre[i][0]=1; 40 for (int x=1;x<=min(m,22877-1);x++) 41 { 42 for (j=0;j<=4;j++) 43 for (i=1;i<=n;i++) 44 pre[j][i]=(pre[j][i-1]*x)%mod[j]; 45 for (i=0;i<=4;i++) res[i]=0; 46 for (i=0;i<=n;i++) 47 for (j=0;j<=4;j++) 48 if (x<mod[j]) 49 res[j]+=(pre[j][i]*a[j][i])%mod[j],res[j]%=mod[j]; 50 for (i=0;i<=4;i++) if (res[i]&&x<mod[i]) ok[i][x]=1; 51 } 52 for (i=1;i<=m;i++) if (jud(i)) ans[++ans[0]]=i; 53 printf("%d\n",ans[0]); 54 for (i=1;i<=ans[0];i++) printf("%d\n",ans[i]); 55 }
标签:
原文地址:http://www.cnblogs.com/Donnie-Darko/p/4767089.html