Educational Codeforces Round 58

D. GCD Counting

题意:

给出n个点的树,每个点有一个权值,找出一条最长的路径使得路径上所有的点的gcd>1

题解:

gcd>1的一定不会有很多。所以暴力搞一下就行,不需要点分治。

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <map>
 6 
 7 using namespace std;
 8 const int maxn=2e5+10;
 9 int head[maxn],Next[2*maxn],to[2*maxn];
10 int a[maxn];
11 int n,sz;
12 void init(){
13     sz=0;
14     memset(head,-1,sizeof(head));
15 }
16 void add_edge(int a,int b){
17     ++sz;
18     to[sz]=b;Next[sz]=head[a];head[a]=sz;
19 }
20 int gcd(int a,int b){
21     if(!b)return a;
22     return gcd(b,a%b);
23 }
24 map<int,int>mp[maxn];
25 int ans;
26 void dfs(int u,int fa){
27     for(int i=head[u];i!=-1;i=Next[i]){
28         int v=to[i];
29         if(v==fa)continue;
30         dfs(v,u);
31         map<int,int>::iterator it,it2;
32         for(it=mp[v].begin();it!=mp[v].end();it++){
33             int g=gcd((*it).first,a[u]);
34             if(g<=1)continue;
35             for(it2=mp[u].begin();it2!=mp[u].end();it2++){
36                 int g2=gcd((*it2).first,g);
37                 if(g2<=1)continue;
38                 ans=max(ans,(*it).second+(*it2).second+1);
39             }
40             mp[u][(*it).first]=max(mp[u][(*it).first],(*it).second);
41         }
42     }
43    // printf("%d %d\n",u,ans);
44     mp[u].clear();
45     mp[u][a[u]]=1;
46     for(int i=head[u];i!=-1;i=Next[i]){
47         int v=to[i];
48         if(v==fa)continue;
49         map<int,int>::iterator it;
50         for(it=mp[v].begin();it!=mp[v].end();it++){
51             int g=gcd(a[u],(*it).first);
52             if(g<=1)continue;
53             mp[u][g]=max(mp[u][g],(*it).second+1);
54             ans=max(ans,(*it).second+1);
55         }
56     }
57 }
58 
59 int main(){
60     scanf("%d",&n);
61     init();
62     for(int i=1;i<=n;i++){
63         scanf("%d",&a[i]);
64         if(a[i]>1)ans=1;
65     }
66 
67     for(int i=1;i<n;i++){
68         int u,v;
69         scanf("%d%d",&u,&v);
70         add_edge(u,v);
71         add_edge(v,u);
72     }
73     dfs(1,0);
74     printf("%d\n",ans);
75 return 0;
76 }
View Code

F. Trucks and Cities

题意:

一条笔直公路上有n个城市,第i个城市在a[i]的位置。有m辆卡车要从一个城市去另一个城市,每一辆卡车有四个属性来描述:s,f,c,r.分别是开始的城市,结束的城市,油耗,可以加油的数量。当卡车到达一个城市的时候就可以加油,每次加油都加满,开始的时候所有的车油都是满的。请你找到最小的V使得所有的卡车都能到达目的地。

题解:

对于一辆从s到t的车,它有k次加油的机会。发现实际上是将s到t的路径以城市为端点最多划分为最大长度最小的k+1段。可以发现这样是最优的。然后就dp+单调队列优化。

代码留坑···

G. (Zero XOR Subset)-less

题意:

给出n个整数a1,a2,...,an。你的任务是将这n个整数分成最多段用下面的方法 1.每个元素都被一段包含 2.每一段都包含至少一个元素 3.每一个非空的段的子集,他们的xor不等于0.

输出最多能分成几段,如果没有合法的分段方法,输出-1.

题解:

当这n个数xor起来如果为0那么肯定是无解的。然后求线性基,线性基的大小r就是答案····

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <iostream>
 5 
 6 using namespace std;
 7 typedef long long LL;
 8 const int maxn=2e5+10;
 9 LL a[maxn];
10 LL x[100];
11 int n;
12 int main(){
13     scanf("%d",&n);
14     LL sum=0;
15     for(int i=1;i<=n;i++){
16         scanf("%I64d",&a[i]);
17         sum^=a[i];
18     }
19     if(sum==0){
20         printf("-1\n");
21         return 0;
22     }
23     int r=0;
24     for(int i=1;i<=n;i++){
25         for(int j=62;j>=0;j--){
26             if(!(a[i]>>j))continue;
27             if(!x[j]){
28                 x[j]=a[i];
29                 r++;
30                 break;
31             }
32             a[i]^=x[j];
33         }
34     }
35     printf("%d\n",r);
36 return 0;
37 }
View Code

 

猜你喜欢

转载自www.cnblogs.com/LQLlulu/p/10388528.html