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 }

 

原文地址:https://www.cnblogs.com/kane0526/p/2781380.html