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 }
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 }