zoukankan      html  css  js  c++  java
  • Acdream原创群赛3(部分题解)

    比赛网址链接:http://www.acdream.net/contest.php?cid=1010

    A题: 按位异或。讨论情况。

    C题:经典广搜。先打表存储各个数的因子。

    G题:可以说是规律题。常规方法nlogn肯定超时。

    H题:简单的二分匹配。

    I题:树形dfs。

    题目大意:给你两个有同样多元素的集合,求一个最小的x,x异或A中所有元素的结果都落在B集合中,且形成一一映射。

    解题思路:关键就在于一一映射,并且先把所有的数都转换成二进制  => A,B中元素每位对应的0和1计算出来。假设第1位, A有a0个0,a1个1,b有b1个1,b0个0,

    如果a0==b0&&a1==b1  那么x对应的此位必为0,否则a0==b1&&a1==b0,x对应的此位必为1.

    View Code
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 using namespace std;
     6 
     7 int  a0[40], a1[40], b0[40], b1[40];
     8 int   x[40];
     9 bool flag;
    10 
    11 void cal()
    12 {
    13     for(int i=0; i<33; i++)
    14     {
    15         if(a0[i]==b0[i]&&a1[i]==b1[i]) x[i]=0;
    16         else if(a1[i]==b0[i]&&a0[i]==b1[i]) x[i]=1;
    17         else
    18         {
    19             flag=1;
    20             break;
    21         }
    22     }
    23 }
    24 
    25 int main()
    26 {
    27     int  n, t;
    28     while(cin >> n)
    29     {
    30         for(int i=0; i<33; i++)
    31             x[i]=a0[i]=a1[i]=b0[i]=b1[i]=0;
    32         for(int i=0; i<n; i++)
    33         {
    34             scanf("%d",&t);
    35             for(int j=0; j<33; j++)
    36             {
    37                 if(t%2&1) a1[j]++;
    38                 else a0[j]++;
    39                 t/=2;
    40             }
    41         }
    42         for(int i=0; i<n; i++)
    43         {
    44             scanf("%d",&t);
    45             for(int j=0; j<33; j++)
    46             {
    47                 if(t%2&1) b1[j]++;
    48                 else b0[j]++;
    49                 t/=2;
    50             }
    51         }
    52         flag=0;
    53         cal();
    54         if(flag)
    55         {
    56             cout << -1 <<endl; continue;
    57         }
    58         long long ans=0, tmp=1;
    59         for(int i=0; i<33; i++)
    60         {
    61             ans+=x[i]*tmp;
    62             tmp*=2;
    63         }
    64         printf("%lld\n",ans);
    65     }
    66     return 0;
    67 }

    C

    题目大意:给出两个数a,b。 a可以变成a+d,的是a的因子。求a变成b最少需要多少步。 

    解题思路:先打表找出每个数的因子,注意1和本身也算。然后就是广搜了。

    View Code
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <queue>
     4 #include <vector>
     5 #include <cmath>
     6 #include <algorithm>
     7 #include <cstring>
     8 using namespace std;
     9 
    10 const int maxn=100005;
    11 int  color[maxn];
    12 int  a, b, Min, ok;
    13 vector<int>vt[maxn];
    14 
    15 struct node
    16 {
    17     int  t;
    18     int  step;
    19 };
    20 
    21 void init()
    22 {
    23     for(int i=1; i<=maxn-5; i++)
    24     {
    25         int t=sqrt(i+1);
    26         for(int j=1; j<=t; j++)
    27         {
    28             if(i%j==0)
    29             {
    30                 vt[i].push_back(j);
    31                 if(i%(i/j)==0) vt[i].push_back(i/j);
    32             }
    33         }
    34     }
    35 }
    36 
    37 void bfs()
    38 {
    39     node s,p;
    40     memset(color,0,sizeof(color));
    41     queue<node>q;
    42     s.t=a;
    43     s.step=0;
    44     q.push(s);
    45     while(!q.empty())
    46     {
    47         p=q.front();
    48         q.pop();
    49         if(p.t>b) continue;
    50         if(p.t==b)
    51         {
    52             ok=1;
    53             cout << p.step <<endl;
    54             break;
    55         }
    56         for(int i=0; i<vt[p.t].size(); i++)
    57         {
    58             s.t=p.t+vt[p.t][i];
    59             s.step=p.step+1;
    60             if(s.t<=b&&!color[s.t])
    61             {
    62                 color[s.t]=1;
    63                 q.push(s);
    64             }
    65         }
    66     }
    67 }
    68 
    69 int main()
    70 {
    71     init();
    72     while(~scanf("%d%d",&a,&b))
    73     {
    74         ok=0;
    75         bfs();
    76         if(!ok) cout <<-1 <<endl;
    77     }
    78     return 0;
    79 }

    G:

    题目大意:C[k]=∑A[i]B[j]mod(109+7)。k=max(i,j)。

    解题思路:开始我用nlogn的方法求c[k],TLE。  列几项仔细分析还是有规律可寻的。

      c[k]=(a[1]+a[2]+……+a[k-1])*b[k]+b[1]+b[2]+……+b[k-1])*a[k]+a[k]*b[k]);

    View Code
     1 #include <stdio.h>
     2 
     3 #define mod 1000000007
     4 #define maxn 100005
     5 long long  a[maxn], b[maxn];
     6 long long c[maxn];
     7 
     8 int main()
     9 {
    10     int  n, t;
    11     long long s1, s2;
    12     while(scanf("%d",&n)!=EOF)
    13     {
    14         for(int i=0; i<n; i++)
    15             c[i]=0;
    16         for(int i=0; i<n; i++)
    17             scanf("%lld",&a[i]);
    18         for(int j=0; j<n; j++)
    19             scanf("%lld",&b[j]);
    20         s1=0, s2=0;
    21         for(int i=0; i<n; i++)
    22         {
    23              c[i]=(c[i]+b[i]*s1+a[i]*s2+a[i]*b[i])%mod;
    24              s1=(s1+a[i])%mod;
    25              s2=(s2+b[i])%mod;
    26         }
    27         for(int i=0; i<n; i++)
    28         {
    29             if(i!=n-1)  printf("%lld ",c[i]%mod);
    30             else printf("%lld\n",c[i]%mod);
    31         }
    32     }
    33     return 0;
    34 }

    H:

    题目大意:给你一些边和一些点,求最大基数匹配。

    解题思路:

    看袁神的解题报告说什么Em什么什么的匹配,很复杂的说。 这题有那么复杂么,怎么感觉都是水水的二分匹配呀。

    View Code
     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 const int maxn=110;
     8 int  visit[maxn];
     9 int  map[maxn][maxn];
    10 int  match[maxn];
    11 int  n;
    12 
    13 bool find(int u)
    14 {
    15     for(int v=1; v<=n; v++)
    16     {
    17         if(map[u][v]&&!visit[v])
    18         {
    19             visit[v]=1;
    20             if(match[v]==-1||find(match[v]))
    21             {
    22                 match[v]=u;
    23                 return true;
    24             }
    25         }
    26     }
    27     return false;
    28 }
    29 
    30 int hungary()
    31 {
    32    memset(match,-1,sizeof(match));
    33    int ans=0;
    34    for(int i=1; i<=n; i++)
    35    {
    36        memset(visit,0,sizeof(visit));
    37        if(find(i)) ans++;
    38    }
    39    return ans;
    40 }
    41 
    42 int main()
    43 {
    44     while(cin >> n)
    45     {
    46         for(int i=1; i<=n; i++)
    47             for(int j=1; j<=n; j++)
    48             {
    49                 scanf("%d",&map[i][j]);
    50             }
    51         cout << hungary()/2 <<endl;
    52     }
    53     return 0;
    54 }

    I:

    题目大意: 给你一颗树。让你删除最多的边,使得剩下的在一起的点还是偶数。

    解题思路: 这题藐视困惑了我好久好久。从n以内的任意一个点开始都行,因为它是一颗树,然后进行树形dfs。把有子树是偶数个点的可以考虑删除。这里我们把要删除的边的下一个点做参照物,这样就能避免是删2个呢还是删4个或者删6个等等。

    View Code
     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 #include <vector>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 const int maxn=100005;
     9 int  f[maxn];
    10 vector<int>vt[maxn];
    11 int n;
    12 
    13 int dfs(int u, int fa)
    14 {
    15     f[u]=1;
    16     for(int i=0; i<vt[u].size(); i++)
    17     {
    18         if(vt[u][i]==fa) continue;
    19         f[u]+=dfs(vt[u][i],u);
    20     }
    21     return f[u];
    22 }
    23 
    24 int main()
    25 {
    26     int   u, v;
    27     while(cin >> n)
    28     {
    29         for(int i=1; i<=n; i++)
    30             vt[i].clear();
    31         for(int i=0; i<n-1; i++)
    32         {
    33             scanf("%d%d",&u,&v);
    34             vt[u].push_back(v);
    35             vt[v].push_back(u);
    36         }
    37         dfs(1,1);
    38         int ans=0;
    39         for(int i=1; i<=n; i++)
    40         {
    41             if(f[i]%2==0) ans++;
    42         }
    43         cout << ans-1 <<endl;
    44     }
    45     return 0;
    46 }

     

  • 相关阅读:
    C# RabbitMQ
    使用HttpClient和WebRequest时POST一个对象的写法
    HTTP中application/x-www-form-urlencoded字符说明
    MVC5 Entity Framework学习
    SQL Server安全
    Entity Framework查询
    COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件失败,原因是出现以下错误: 80070005 拒绝访问。最新解决方案
    js中精度问题以及解决方案
    string.format
    t-sql对被除数为0&除数小于被除数结果为0&除法保留2位小数的处理
  • 原文地址:https://www.cnblogs.com/kane0526/p/2781380.html
Copyright © 2011-2022 走看看