zoukankan      html  css  js  c++  java
  • 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
    ",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:
    ",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
    ",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

  • 相关阅读:
    在Delphi中如何创建和使用udl文件
    《深入浅出struts》读书笔记(2)
    指针与数组
    《深入浅出struts》读书笔记
    《深入浅出struts》读书笔记(3)
    《深入浅出struts》读书笔记(3)
    指针的简单使用
    指针的简单使用
    指针与数组
    《深入浅出struts》读书笔记
  • 原文地址:https://www.cnblogs.com/gaolzzxin/p/3944682.html
Copyright © 2011-2022 走看看