matrix_last_acm_4

2013 ACM-ICPC吉林通化全国邀请赛 

 

A http://acm.hust.edu.cn/vjudge/contest/view.action?cid=97654#problem/A

题意:输入12个数,输出平均值,但是不能有多余的后缀的零。直接。2f wa了一发。

解法:用sprintf 放到char【】里,然后去掉后面的0.

 

 1 //#define debug
 2 //#define txtout
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<cmath>
 7 #include<cctype>
 8 #include<ctime>
 9 #include<iostream>
10 #include<algorithm>
11 #include<vector>
12 #include<queue>
13 #include<stack>
14 #include<map>
15 #include<set>
16 #define mt(a,b) memset(a,b,sizeof(a))
17 using namespace std;
18 typedef long long LL;
19 const double eps=1e-8;
20 const double pi=acos(-1.0);
21 const int inf=0x3f3f3f3f;
22 const int M=1e2+10;
23 double a[M];
24 char buffer[M];
25 void solve(){
26     double sum=0;
27     for(int i=0;i<12;i++){
28         sum+=a[i];
29     }
30     sprintf(buffer,"$%.2f",sum/12);
31     int len=strlen(buffer);
32     if(buffer[len-1]=='0'){
33         len--;
34         if(buffer[len-1]=='0'){
35             len-=2;
36         }
37     }
38     buffer[len]=0;
39 }
40 int main(){
41     #ifdef txtout
42     freopen("in.txt","r",stdin);
43     freopen("out.txt","w",stdout);
44     #endif
45     int t;
46     while(~scanf("%d",&t)){
47         while(t--){
48             for(int i=0;i<12;i++){
49                 scanf("%lf",&a[i]);
50             }
51             solve();
52             puts(buffer);
53         }
54     }
55     return 0;
56 }
View Code

 

 

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=97654#problem/D

题意:给n点m边无向图,问按输入顺序依次删去第i条边后连通块的个数。

解法:倒着用并查集。

 

 1 //#define debug
 2 //#define txtout
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<cmath>
 7 #include<cctype>
 8 #include<ctime>
 9 #include<iostream>
10 #include<algorithm>
11 #include<vector>
12 #include<queue>
13 #include<stack>
14 #include<map>
15 #include<set>
16 #define mt(a,b) memset(a,b,sizeof(a))
17 using namespace std;
18 typedef long long LL;
19 const double eps=1e-8;
20 const double pi=acos(-1.0);
21 const int inf=0x3f3f3f3f;
22 const int M=1e5+10;
23 int n,m;
24 struct E {
25     int u,v;
26 } e[M];
27 int answer[M];
28 class UnionFindSet { ///并查集
29     static const int MV=1e4+10; ///点的个数
30     int par[MV],num[MV];
31     void add(int son,int fa) {
32         par[fa]+=par[son];
33         par[son]=fa;
34         num[fa]+=num[son];
35     }
36 public:
37     void init(int n) {
38         for(int i=0; i<=n; i++) {
39             num[i]=1;
40             par[i]=-1;
41         }
42     }
43     int getroot(int x) {
44         int i=x,j=x,temp;
45         while(par[i]>=0) i=par[i];
46         while(j!=i) {
47             temp=par[j];
48             par[j]=i;
49             j=temp;
50         }
51         return i;
52     }
53     bool unite(int x,int y) {
54         int p=getroot(x);
55         int q=getroot(y);
56         if(p==q) return false;
57         if(par[p]>par[q]) {
58             add(p,q);
59         } else {
60             add(q,p);
61         }
62         return true;
63     }
64     int getnum(int id) { ///返回该点所在集合包含的点数
65         return num[getroot(id)];
66     }
67 } ufs;
68 void solve() {
69     int result=n;
70     ufs.init(n);
71     for(int i=m-1;i>=0;i--){
72         answer[i]=result;
73         if(ufs.unite(e[i].u,e[i].v)){
74             result--;
75         }
76     }
77 }
78 int main() {
79 #ifdef txtout
80     freopen("in.txt","r",stdin);
81     freopen("out.txt","w",stdout);
82 #endif
83     while(~scanf("%d%d",&n,&m)) {
84         for(int i=0; i<m; i++) {
85             scanf("%d%d",&e[i].u,&e[i].v);
86         }
87         solve();
88         for(int i=0; i<m; i++) {
89             printf("%d\n",answer[i]);
90         }
91     }
92     return 0;
93 }
View Code

 

 

 

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=97654#problem/E

题意:求有多少个3元组abc满足 gcd(a,b,c)=G,lcm(a,b,c)=L

解法:质因数分解可以看出,gcd是3个数都有的质因子的次方的最小值,lcm是三个数的每一种质因子的次方最大值,那么lcm一定是gcd的倍数。所以不是倍数答案为0。当lcm==gcd时,只有一种,就是3个数相等。否则就是求lcm/gcd=value分配到abc的方法数。考虑value的一种质因子p,次方a,p^a,有两种情况,一种是只有一个有p,那么这个必须是p^a,这种情况有3个选择。第二种是有两个有p,那么至少一个次方是a,另一个可以1到a,所以一共有2*a种,但是两个都是a的会多算一次,所以一共2*a-1种,从3个中选出两个放p有C(3,2)种,所以最后是3+3*(2*a-1)种情况。

 

 1 //#define debug
 2 //#define txtout
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<cmath>
 7 #include<cctype>
 8 #include<ctime>
 9 #include<iostream>
10 #include<algorithm>
11 #include<vector>
12 #include<queue>
13 #include<stack>
14 #include<map>
15 #include<set>
16 #define mt(a,b) memset(a,b,sizeof(a))
17 using namespace std;
18 typedef long long LL;
19 const double eps=1e-8;
20 const double pi=acos(-1.0);
21 const int inf=0x3f3f3f3f;
22 const int M=1e5+10;
23 int G,L;
24 int solve(){
25     if(L%G) return 0;
26     if(L==G) return 1;
27     L/=G;
28     int result=1;
29     for(int i=2;i*i<=L;i++){
30         if(L%i) continue;
31         int a=0;
32         while(L%i==0){
33             L/=i;
34             a++;
35         }
36         result*=6*a;
37     }
38     if(L>1) result*=6;
39     return result;
40 }
41 int main(){
42     #ifdef txtout
43     freopen("in.txt","r",stdin);
44     freopen("out.txt","w",stdout);
45     #endif
46     int t;
47     while(~scanf("%d",&t)){
48         while(t--){
49             scanf("%d%d",&G,&L);
50             printf("%d\n",solve());
51         }
52     }
53     return 0;
54 }
View Code

 

 

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=97654#problem/G

题意:给n*m的棋盘,上面有q个点,其他位置可以放炮,就是象棋的规则,要保证最后放置的炮不能被吃,也就是不存在两个炮之间有点或者跑。

解法:dfs所有情况,每次放炮前先判一下行和列是否会被吃。

 

  1 //#define debug
  2 //#define txtout
  3 #include<cstdio>
  4 #include<cstdlib>
  5 #include<cstring>
  6 #include<cmath>
  7 #include<cctype>
  8 #include<ctime>
  9 #include<iostream>
 10 #include<algorithm>
 11 #include<vector>
 12 #include<queue>
 13 #include<stack>
 14 #include<map>
 15 #include<set>
 16 #define mt(a,b) memset(a,b,sizeof(a))
 17 using namespace std;
 18 typedef long long LL;
 19 const double eps=1e-8;
 20 const double pi=acos(-1.0);
 21 const int inf=0x3f3f3f3f;
 22 const int M=1e2+10;
 23 struct Q{
 24     int x,y;
 25 }p[M];
 26 int n,m,q;
 27 bool ispoint[M][M];
 28 bool choose[M][M];
 29 int result;
 30 int dx[]={0,0,1,-1};
 31 int dy[]={1,-1,0,0};
 32 void init(){
 33     for(int i=0;i<n;i++){
 34         for(int j=0;j<m;j++){
 35             ispoint[i][j]=false;
 36             choose[i][j]=false;
 37         }
 38     }
 39     for(int i=0;i<q;i++){
 40         ispoint[p[i].x][p[i].y]=true;
 41     }
 42 }
 43 bool inside(int x,int y){
 44     return x>=0&&x<n&&y>=0&&y<m;
 45 }
 46 bool eat(int x,int y,int d){
 47     int tx=x+dx[d];
 48     int ty=y+dy[d];
 49     while(inside(tx,ty)&&!choose[tx][ty]&&!ispoint[tx][ty]){
 50         tx+=dx[d];
 51         ty+=dy[d];
 52     }
 53     if(!inside(tx,ty)) return false;
 54     tx+=dx[d];
 55     ty+=dy[d];
 56     while(inside(tx,ty)&&!choose[tx][ty]&&!ispoint[tx][ty]){
 57         tx+=dx[d];
 58         ty+=dy[d];
 59     }
 60     if(!inside(tx,ty)) return false;
 61     return choose[tx][ty];
 62 }
 63 bool judge(int x,int y){
 64     for(int i=0;i<4;i++){
 65         if(eat(x,y,i)) return false;
 66     }
 67     return true;
 68 }
 69 void dfs(int x,int y,int sum){
 70     if(x==n){
 71         result=max(result,sum);
 72         return ;
 73     }
 74     if(y==m) return dfs(x+1,0,sum);
 75     if(ispoint[x][y]) return dfs(x,y+1,sum);
 76     dfs(x,y+1,sum);
 77     if(judge(x,y)){
 78         choose[x][y]=true;
 79         dfs(x,y+1,sum+1);
 80         choose[x][y]=false;
 81     }
 82 }
 83 int solve(){
 84     init();
 85     result=0;
 86     dfs(0,0,0);
 87     return result;
 88 }
 89 int main(){
 90     #ifdef txtout
 91     freopen("in.txt","r",stdin);
 92     freopen("out.txt","w",stdout);
 93     #endif
 94     while(~scanf("%d%d%d",&n,&m,&q)){
 95         for(int i=0;i<q;i++){
 96             scanf("%d%d",&p[i].x,&p[i].y);
 97         }
 98         printf("%d\n",solve());
 99     }
100     return 0;
101 }
View Code

 

 H http://acm.hust.edu.cn/vjudge/contest/view.action?cid=97654#problem/H

题意:给两堆牌,张数都为n,AB轮流拿,每次可以拿任意一堆的顶部或者底部,A先拿,AB都足够聪明,问最后A能得的最大分数。

解法:定义dp【x1】【y1】【x2】【y2】表示先手遇到 第一堆剩 x1到y1区间,第二堆剩 x2到y2区间时能得到的最大分数,答案就是dp[1][n][1][n].转移有4个,就是两堆的头尾都可以拿。比如拿a【x1】位置的牌 ,那么 就等于后手遇到了 dp【x1+1】【y1】【x2】【y2】的情况, 用后手的区间和减去后手的最大得分再加上a【x1】就是先手可能获得的得分。

 

  1 //#define debug
  2 //#define txtout
  3 #include<cstdio>
  4 #include<cstdlib>
  5 #include<cstring>
  6 #include<cmath>
  7 #include<cctype>
  8 #include<ctime>
  9 #include<iostream>
 10 #include<algorithm>
 11 #include<vector>
 12 #include<queue>
 13 #include<stack>
 14 #include<map>
 15 #include<set>
 16 #define mt(a,b) memset(a,b,sizeof(a))
 17 using namespace std;
 18 typedef long long LL;
 19 const double eps=1e-8;
 20 const double pi=acos(-1.0);
 21 const int inf=0x3f3f3f3f;
 22 const int M=25;
 23 int a[M];
 24 int b[M];
 25 int sa[M];
 26 int sb[M];
 27 int n;
 28 int dp[M][M][M][M];
 29 void init_sum(int sum[],int v[]){
 30     sum[0]=0;
 31     for(int i=1;i<=n;i++){
 32         sum[i]=sum[i-1]+v[i];
 33     }
 34 }
 35 void init_dp(){
 36     for(int x1=0;x1<=n;x1++){
 37         for(int y1=0;y1<=n;y1++){
 38             for(int x2=0;x2<=n;x2++){
 39                 for(int y2=0;y2<=n;y2++){
 40                     dp[x1][y1][x2][y2]=-1;
 41                 }
 42             }
 43         }
 44     }
 45 }
 46 int get_sum(int x1,int y1,int x2,int y2){
 47     int result=sa[y1]+sb[y2];
 48     if(x1) result-=sa[x1-1];
 49     if(x2) result-=sb[x2-1];
 50     return result;
 51 }
 52 int dfs(int x1,int y1,int x2,int y2){
 53     int& answer=dp[x1][y1][x2][y2];
 54     if(answer!=-1) return answer;
 55     if(x1<y1){
 56         answer=max(answer,a[x1]+get_sum(x1+1,y1,x2,y2)-dfs(x1+1,y1,x2,y2));
 57         answer=max(answer,a[y1]+get_sum(x1,y1-1,x2,y2)-dfs(x1,y1-1,x2,y2));
 58     }
 59     if(x2<y2){
 60         answer=max(answer,b[x2]+get_sum(x1,y1,x2+1,y2)-dfs(x1,y1,x2+1,y2));
 61         answer=max(answer,b[y2]+get_sum(x1,y1,x2,y2-1)-dfs(x1,y1,x2,y2-1));
 62     }
 63     if(x1==y1&&x1){
 64         answer=max(answer,a[x1]+get_sum(0,0,x2,y2)-dfs(0,0,x2,y2));
 65     }
 66     if(x2==y2&&x2){
 67         answer=max(answer,b[x2]+get_sum(x1,y1,0,0)-dfs(x1,y1,0,0));
 68     }
 69     return answer;
 70 }
 71 int solve(){
 72     init_sum(sa,a);
 73     init_sum(sb,b);
 74     init_dp();
 75     dp[0][0][0][0]=0;
 76     for(int i=1;i<=n;i++){
 77         dp[i][i][0][0]=a[i];
 78         dp[0][0][i][i]=b[i];
 79     }
 80     return dfs(1,n,1,n);
 81 }
 82 int main(){
 83     #ifdef txtout
 84     freopen("in.txt","r",stdin);
 85     freopen("out.txt","w",stdout);
 86     #endif
 87     int t;
 88     while(~scanf("%d",&t)){
 89         while(t--){
 90             scanf("%d",&n);
 91             for(int i=1;i<=n;i++){
 92                 scanf("%d",&a[i]);
 93             }
 94             for(int i=1;i<=n;i++){
 95                 scanf("%d",&b[i]);
 96             }
 97             printf("%d\n",solve());
 98         }
 99     }
100     return 0;
101 }
View Code

 

 

 

 

end

 

posted on 2015-11-01 15:20  gaolzzxin  阅读(212)  评论(0编辑  收藏  举报