2013 Asia Chengdu Regional Contest

hdu 4786 Fibonacci Tree http://acm.hdu.edu.cn/showproblem.php?pid=4786

copyright@ts 算法源于ts,用最小生成树可以求出最小权值,把所有边权取反可以求出最大权值,算法是如果有个斐波那契数在最小到最大值之间,就一定能构成。也就是如果大了就把1边换成0边,反之亦然。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define mt(a,b) memset(a,b,sizeof(a))
  5 using namespace std;
  6 const int M=100010;
  7 class Kruskal { ///最小生成树(无向图)o(ME*logME)
  8     typedef int typec;///边权的类型
  9     static const int ME=M;///边的个数
 10     static const int MV=M;///点的个数
 11     class UnionFindSet { ///并查集
 12         int par[MV];
 13     public:
 14         void init() {
 15             mt(par,-1);
 16         }
 17         int getroot(int x) {
 18             int i=x,j=x,temp;
 19             while(par[i]>=0) i=par[i];
 20             while(j!=i) {
 21                 temp=par[j];
 22                 par[j]=i;
 23                 j=temp;
 24             }
 25             return i;
 26         }
 27         bool unite(int x,int y) {
 28             int p=getroot(x);
 29             int q=getroot(y);
 30             if(p==q)return false;
 31             if(par[p]>par[q]) {
 32                 par[q]+=par[p];
 33                 par[p]=q;
 34             } else {
 35                 par[p]+=par[q];
 36                 par[q]=p;
 37             }
 38             return true;
 39         }
 40     } f;
 41     struct E {
 42         int u,v;
 43         typec w;
 44         friend bool operator < (E a,E b) {
 45             return a.w<b.w;
 46         }
 47     } e[ME];
 48     int le,num,n;
 49     typec res;
 50 public:
 51     void init(int tn){///传入点的个数
 52         n=tn;
 53         le=res=0;
 54         f.init();
 55         num=1;
 56     }
 57     void add(int u,int v,typec w) {
 58         e[le].u=u;
 59         e[le].v=v;
 60         e[le].w=w;
 61         le++;
 62     }
 63     typec solve(){///返回-1不连通
 64         sort(e,e+le);
 65         for(int i=0; i<le&&num<n; i++) {
 66             if(f.unite(e[i].u,e[i].v)) {
 67                 num++;
 68                 res+=e[i].w;
 69             }
 70         }
 71         if(num<n) res=-1;
 72         return res;
 73     }
 74 }gx;
 75 struct IN{
 76     int u,v,w;
 77 }e[M];
 78 int F[32];
 79 void yes(){
 80     puts("Yes");
 81 }
 82 void no(){
 83     puts("No");
 84 }
 85 int main(){
 86     F[0]=F[1]=1;
 87     for(int i=2;i<32;i++){
 88         F[i]=F[i-1]+F[i-2];
 89     }
 90     int t,n,m;
 91     while(~scanf("%d",&t)){
 92         for(int cas=1;cas<=t;cas++){
 93             scanf("%d%d",&n,&m);
 94             gx.init(n);
 95             for(int i=0;i<m;i++){
 96                 scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
 97                 gx.add(e[i].u,e[i].v,e[i].w);
 98             }
 99             int sma=gx.solve();
100             printf("Case #%d: ",cas);
101             if(sma==-1){
102                 no();
103                 continue;
104             }
105             gx.init(n);
106             for(int i=0;i<m;i++){
107                 gx.add(e[i].u,e[i].v,-e[i].w);
108             }
109             int big=-gx.solve();
110             bool flag=false;
111             for(int i=0;i<32;i++){
112                 if(sma<=F[i]&&F[i]<=big){
113                     flag=true;
114                     break;
115                 }
116             }
117             if(flag){
118                 yes();
119             }
120             else{
121                 no();
122             }
123         }
124     }
125     return 0;
126 }
View Code

 

Hard Disk Drive http://acm.hdu.edu.cn/showproblem.php?pid=4788

简单计算。1kb当成1000b,但是计算机当成1024b是1kb,所以输入1kb,实际上只有1000b/1024b个kb。

 1 #include<cstdio>
 2 char op[8];
 3 char cmp[16][16]={"B","KB","MB","GB","TB","PB","EB","ZB","YB"};
 4 int main(){
 5     int t,pre;
 6     double now;
 7     while(~scanf("%d",&t)){
 8         for(int cas=1;cas<=t;cas++){
 9             scanf("%d[%s",&pre,op);
10             now=pre;
11             int num=0;
12             for(int i=0;i<9;i++){
13                 if(cmp[i][0]==op[0]){
14                     num=i;
15                     break;
16                 }
17             }
18             for(int i=0;i<num;i++){
19                 now*=1000;
20                 now/=1024;
21             }
22             printf("Case #%d: %.2f",cas,(pre-now)*100/pre);
23             puts("%");
24         }
25     }
26     return 0;
27 }
View Code

 

 

Just Random http://acm.hdu.edu.cn/showproblem.php?pid=4790

题目要求 算 (x + y) mod p = m的概率,其中x属于a,b区间  y属于c,d区间。copyright@ts

考虑选择是随机等概率的。所以概率是出现上式的个数除以总的个数。总的个数好求,就是这个矩形区间长乘宽。

然后可以将矩形每一个点的值画出来,

                   1  2  3  4  5  这个是长度区间

    0  1  2  3  4  5

    1  2  3  4  5  6

    2  3  4  5  6  7

这个是宽度区间

可以发现斜着的值是相等的。

矩阵中3,4,5的个数都是相等的,1,2构成的三角形分为第一区间,中间都相等的分为第二区间,后面的三角形分为第三区间。

因为是mod p  所以每p个会出现一个,所以第一第三区间中都是等差数列,求首项公差项数去求和,中间只要算出个数乘斜着的长度就是总的个数。

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 typedef __int64 LL;
 5 LL gcd(LL a,LL b) { ///最大公约数
 6     return b?gcd(b,a%b):a;
 7 }
 8 int main() {
 9     int t;
10     LL a,b,c,d,p,m;
11     while(~scanf("%d",&t)) {
12         for(int cas=1; cas<=t; cas++) {
13             scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&a,&b,&c,&d,&p,&m);
14             if((b-a+1)>(d-c+1)) {
15                 swap(a,c);
16                 swap(b,d);
17             }
18             LL ans=0;
19             LL k=(a+c-m)/p;///第一个区间
20             if(a+c-m>=0&&(a+c-m)%p!=0) {
21                 k++;
22             }
23             if(k*p+m<=b+c-1) {
24                 LL first=k*p+m;
25                 LL t=first-c;
26                 LL a1=t-a+1;
27                 LL num=(b+c-1-first)/p+1;
28                 ans+=(a1+a1+p*(num-1))*num/2;
29             }
30             k = (b+c-m)/p;///第二个区间
31             if((b+c-m)>=0&&(b+c-m)%p!=0) {
32                 k++;
33             }
34             if(k*p+m<=a+d) {
35                 LL first=k*p+m;
36                 LL num=(a+d-first)/p+1;
37                 ans+=num*(b-a+1);
38             }
39             k=(a+d+1-m)/p;///第三个区间
40             if(a+d+1-m>=0&&(a+d+1-m)%p!=0) {
41                 k++;
42             }
43             if(k*p+m<=b+d) {
44                 LL first=k*p+m;
45                 LL num=(b+d-first)/p+1;
46                 LL t=first-d;
47                 LL a1=b-t+1;
48                 ans+=(a1+a1-p*(num-1))*num/2;
49             }
50             printf("Case #%d: ",cas);
51             if(!ans) {
52                 puts("0/1");
53                 continue;
54             }
55             LL fenmu=(b-a+1)*(d-c+1);
56             LL d=gcd(ans,fenmu);
57             printf("%I64d/%I64d\n",ans/d,fenmu/d);
58         }
59     }
60     return 0;
61 }
View Code

 

 

Assignment For Princess http://acm.hdu.edu.cn/showproblem.php?pid=4781

构造一个图,n点m边,边权是1到m。保证没有重边没有自环。保证两两可达。任意一个回路的边权和要是3的倍数。

首先把n个点连成一个环。先满足两两可达的条件,1到2,。。。。n-1到n就直接用前一个的点的值来作为边权,n到1要算一下之前的和,然后选一个值保证总和是3的倍数。

构造成环以后,剩下的边只要考虑形成的环是3的倍数就行。

n^2的枚举两个点来连,能连的条件是他们之间没有边,并且构成的回路要是3的倍数。假设当前枚举到我们要加 i ---> j 如果和我们之前的大环小到大是同向的,那么就会和大环中的 j到i构成环。也就是说这个边 mod 3的余数 要和大环中i到j的余数相同。比如图中,如果想加入1到3,那么他会和原图的3->4->1构成环也就是他mod3要等于原来1到2到3的和mod3.

如果是反向的,那就要和大环中求和 mod 3 ==0 。可以预处理出大环1到 i的和,通过相减的关系就可以求出任意一段的和。

如图,如果要加3到1的,那就会和原来的1到2到3 形成环。也就是要和1到2到3的和相加是3的倍数。

 1 #include<cstdio>
 2 #include<cstring>
 3 #define mt(a,b) memset(a,b,sizeof(a))
 4 const int M=1024;
 5 struct G{
 6     struct E{
 7         int u,v,w;
 8     }e[M];
 9     int le;
10     void init(){
11         le=0;
12     }
13     void add(int u,int v,int w){
14         e[le].u=u;
15         e[le].v=v;
16         e[le].w=w;
17         le++;
18     }
19 }g;
20 bool mat[M][M];
21 int sum[M];
22 bool vis[M];
23 int main() {
24     int t,n,m;
25     while(~scanf("%d",&t)) {
26         for(int cas=1; cas<=t; cas++) {
27             scanf("%d%d",&n,&m);
28             printf("Case #%d:\n",cas);
29             g.init();
30             sum[0]=0;
31             sum[1]=0;
32             mt(vis,0);
33             for(int i=1; i<n; i++) {
34                 vis[i]=true;
35                 g.add(i,i+1,i);
36                 sum[i+1]=sum[i]+i;
37             }
38             for(int i=0; i<3; i++) {
39                 if((n+i+sum[n])%3==0) {
40                     vis[n+i]=true;
41                     g.add(n,1,n+i);
42                     break;
43                 }
44             }
45             mt(mat,0);
46             for(int i=0; i<g.le; i++) {
47                 int u=g.e[i].u;
48                 int v=g.e[i].v;
49                 mat[u][v]=true;
50                 mat[v][u]=true;
51             }
52             bool ok=true;
53             for(int e=n; e<=m; e++) {
54                 if(vis[e]) continue;
55                 bool add=false;
56                 for(int i=1; i<=n; i++) {
57                     for(int j=1; j<=n; j++) {
58                         if(i==j) continue;
59                         if(mat[i][j]) continue;
60                         if(i<j) {
61                             int tmp=sum[j]-sum[i];
62                             if(e%3==tmp%3) {
63                                 g.add(i,j,e);
64                                 add=true;
65                                 mat[i][j]=true;
66                                 mat[j][i]=true;
67                                 break;
68                             }
69                         } else {
70                             int tmp=sum[j]-sum[i];
71                             if((e+tmp)%3==0) {
72                                 g.add(i,j,e);
73                                 add=true;
74                                 mat[i][j]=true;
75                                 mat[j][i]=true;
76                                 break;
77                             }
78                         }
79                     }
80                     if(add) break;
81                 }
82                 if(!add) {
83                     ok=false;
84                     break;
85                 }
86             }
87             if(ok) {
88                 for(int i=0; i<g.le; i++) {
89                     printf("%d %d %d\n",g.e[i].u,g.e[i].v,g.e[i].w);
90                 }
91             } else {
92                 puts("-1");
93             }
94         }
95     }
96     return 0;
97 }
View Code

 

end

posted on 2014-08-29 12:28  gaolzzxin  阅读(210)  评论(0编辑  收藏  举报