FZU 2229 Calculus Midterm 链接 Calculus Midterm
题意 计算总分判断即可
参考代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include <stdio.h> int main () { int x,y,z; while (scanf ("%d%d%d" ,&x,&y,&z)!=EOF){ int ans=x*3 +y*2 +z*6 ; if (ans<60 ) printf ("Exam was too hard.\n" ); else printf ("I passed the exam.\n" ); printf ("%d\n" ,ans); } return 0 ; }
FZU 2230 翻翻棋 链接 翻翻棋
分析 计算红方和黑方之间所需的最小步数,若为偶数,黑方赢,否则红方赢
参考代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> int main () { int T; scanf ("%d" ,&T); int x1,y1,x2,y2; while (T--){ for (int i=0 ;i<4 ;i++){ char s[10 ]; scanf ("%s" ,s); for (int j=0 ;j<8 ;j++){ if (s[j]=='.' ){ x1=i; y1=j; } else if (s[j]=='*' ){ x2=i; y2=j; } } } int tmp=abs (x1-x2)+abs (y1-y2); if (tmp%2 ==0 ) printf ("Black win\n" ); else printf ("Red win\n" ); } return 0 ; }
FZU 2231 平行四边形数 链接 平行四边形数
题意 给定n个点坐标,求能组成多少平行四边形
分析 最直接的思想是每次枚举四个点,根据平行四边形的判定定理判断,可是时间复杂度挺高O(n^4). 思路二:求出所有边的边长,每次枚举对边,根据对边平行且相等来判定,时间复杂度也一样。 稍微优化:将边按边长排序,枚举时若两边不相等,就不用往后继续了。但是最坏情况复杂度也一样。 可能这个题数据太弱,这样做A了。还有一个更好的思路: 根据平行四边形对角线互相平分,求出每条线段的中点,若有m条线段中点相同, 则可构成m*(m-1)/2个平行四边形。这样时间复杂度为O(n^2)
参考代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 #include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> #include <algorithm> using namespace std ;#define eps 1e-5 #define N 505 struct Point{ double x,y; }p[N]; struct Edge{ int u,v; double dis; }edge[N*N]; bool cmp (Edge a,Edge b) { return a.dis<b.dis; } double Distance (Point a,Point b) { return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y); } bool isPal (Edge a,Edge b) { Point s; s.x=p[a.v].x-p[a.u].x; s.y=p[a.v].y-p[a.u].y; Point t; t.x=p[b.v].x-p[b.u].x; t.y=p[b.v].y-p[b.u].y; if (fabs (s.x*t.y-s.y*t.x)<eps) return true ; return false ; } bool check (int a,int b) { if (edge[a].u==edge[b].u||edge[a].u==edge[b].v||edge[a].v==edge[b].u||edge[a].v==edge[b].v) return false ; return isPal(edge[a],edge[b]); } int main () { int n; while (scanf ("%d" ,&n)!=EOF){ for (int i=1 ;i<=n;i++) scanf ("%lf%lf" ,&p[i].x,&p[i].y); int cnt=0 ; for (int i=1 ;i<=n;i++){ for (int j=i+1 ;j<=n;j++){ edge[cnt].u=i; edge[cnt].v=j; edge[cnt++].dis=Distance(p[i],p[j]); } } sort(edge,edge+cnt,cmp); int now=0 ,ans=0 ; for (int i=0 ;i<cnt;i++){ now=i+1 ; while (now<cnt&&fabs (edge[i].dis-edge[now].dis)<eps){ if (check(i,now)) ans++; now++; } } printf ("%d\n" ,ans/2 ); } return 0 ; }
FZU 2232 炉石传说 链接 炉石传说
题意 给定GG学长的n个随从的生命值及攻击力,对手的n个随从的生命力及攻击力,问GG学长能否一回合杀死对手所有随从,且自己的随从都存活。
分析 二分图的最大匹配 根据题意,每个随从A与对手随从B对战,要想A杀死B,且A不死,则A的攻击力要不小于B的生命值,且A的生命值要大于B的攻击力。即n个随从的匹配都满足此条件就能达到目的。 二分图的最大匹配—匈牙利算法,若最大匹配数等于n则可以。
参考代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <stdio.h> #include <string.h> #define N 105 struct stu{ int att; int lf; }; struct stu a[N],b[N];bool used[N];int link[N],n;int dfs (int pos) { for (int i=1 ;i<=n;i++){ if (!used[i]&&a[pos].att>=b[i].lf&&a[pos].lf>b[i].att){ used[i]=true ; if (link[i]==-1 ||dfs(link[i])){ link[i]=pos; return 1 ; } } } return 0 ; } int main () { int T; scanf ("%d" ,&T); while (T--){ scanf ("%d" ,&n); for (int i=1 ;i<=n;i++) scanf ("%d%d" ,&a[i].lf,&a[i].att); for (int i=1 ;i<=n;i++) scanf ("%d%d" ,&b[i].lf,&b[i].att); memset (link,-1 ,sizeof (link)); int ans=0 ; for (int i=1 ;i<=n;i++){ memset (used,0 ,sizeof (used)); ans+=dfs(i); } if (ans==n) printf ("Yes\n" ); else printf ("No\n" ); } return 0 ; }
FZU 2236 第十四个目标 链接 第十四个目标
题意 已知n个数,求严格递增子序列的个数,如(1,3,2)的严格递增子序列有(1)、(3)、(2)、(1,3)、(1,2),共5个。
分析 树状数组+dp 设dp[i]为以i结尾的递增子序列的个数,则$dp[i]=\Sigma{dp[j]}+1$,其中j<i且a[j]<a[i] 即对于j<i,a[j]<a[i],a[j]会对a[i]贡献dp[j]的贡献值。但是其复杂度O(n^2)效率太低 可以用树状数组优化成 O(nlgn),题目数据挺大到1e9,所以需Hash处理
参考代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #include <stdio.h> #include <algorithm> #include <string.h> #define N 100010 #define mod 1000000007 using namespace std ;typedef long long LL;LL c[N]; int a[N],id[N],m;int lowbit (int x) { return x&(-x); } void update (int x,int val) { for (int i=x;i<=m;i+=lowbit(i)) c[i]=(c[i]+val)%mod; } LL query (int x) { LL ans=0 ; for (int i=x;i>=1 ;i-=lowbit(i)) ans=(ans+c[i])%mod; return ans; } int main () { int n; while (scanf ("%d" ,&n)!=EOF){ for (int i=1 ;i<=n;i++){ scanf ("%d" ,&a[i]); id[i]=a[i]; } sort(id+1 ,id+n+1 ); m=unique(id+1 ,id+n+1 )-id; LL ans=0 ; memset (c,0 ,sizeof (c)); for (int i=1 ;i<=n;i++){ int pos=lower_bound(id+1 ,id+m,a[i])-id; int sum=(query(pos-1 )+1 )%mod; ans=(ans+sum)%mod; update(pos,sum); } printf ("%lld\n" ,ans); } return 0 ; }