RT,即将退役的人懒得一篇篇写题解,于是有了这个东西
CF1004E
树上选一条不超过k个点的链,最小化其余点到链上点的最大距离
这个思路很有意思,不像平时一般的树上问题,是从叶子开始一点点贪心合并直到合得只剩一条链,这条链就是最后的答案
用优先队列完成,复杂度$O(nlog n)$
1 #include<set> 2 #include<queue> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 const int N=200005; 8 struct a{int pts,len;}; 9 bool operator < (a x,a y) 10 { 11 return x.len>y.len; 12 } 13 set<pair<int,int> > st[N]; 14 priority_queue<a> hp; 15 int n,k,t1,t2,t3,siz,ans; 16 int main() 17 { 18 scanf("%d%d",&n,&k),siz=n; 19 for(int i=1;i<n;i++) 20 { 21 scanf("%d%d%d",&t1,&t2,&t3); 22 st[t1].insert(make_pair(t2,t3)); 23 st[t2].insert(make_pair(t1,t3)); 24 } 25 for(int i=1;i<=n;i++) 26 if(st[i].size()==1) 27 hp.push((a){i,(*st[i].begin()).second}); 28 while(hp.size()>2||k<siz) 29 { 30 a mn=hp.top(); hp.pop(),siz--,ans=mn.len; 31 int p=mn.pts,nxt=(*st[p].begin()).first; 32 st[nxt].erase(st[nxt].lower_bound(make_pair(p,0))); 33 if(st[nxt].size()==1) 34 hp.push((a){nxt,ans+(*st[nxt].begin()).second}); 35 } 36 printf("%d",ans); 37 return 0; 38 }
CF772D
题面看题吧
感觉这题没啥意义,因为考场不太可能想出来
这个东西可以理解为十进制下的“与”(=。=???),记录每个权值出现的次数,出现的和,出现的平方和,搞一个十进制FWT来做
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=1e6+60,M=1e6,mod=1e9+7; 6 int n,rd,a[N],b[N],c[N],f[N],pw2[N]; long long ans; 7 void Add(int &x,int y) 8 { 9 x+=y; 10 if(x>=mod) x-=mod; 11 } 12 void Trans(int *arr,int typ) 13 { 14 if(~typ) 15 { 16 for(int i=1;i<M;i*=10) 17 for(int j=M-1;~j;j--) 18 if(j/i%10) Add(arr[j-i],arr[j]); 19 } 20 else 21 { 22 for(int i=1;i<M;i*=10) 23 for(int j=0;j<M;j++) 24 if(j/i%10) Add(arr[j-i],mod-arr[j]); 25 } 26 } 27 int main() 28 { 29 scanf("%d",&n),pw2[0]=1; 30 for(int i=1;i<=n;i++) pw2[i]=2ll*pw2[i-1]%mod; 31 for(int i=1;i<=n;i++) 32 { 33 scanf("%d",&rd); 34 a[rd]++,Add(b[rd],rd),Add(c[rd],1ll*rd*rd%mod); 35 } 36 Trans(a,1),Trans(b,1),Trans(c,1); 37 for(int i=0;i<M;i++) 38 if(a[i]) f[i]=(a[i]==1)?c[i]:1ll*pw2[a[i]-2]*(1ll*b[i]*b[i]%mod+c[i])%mod; 39 Trans(f,-1); 40 for(int i=0;i<M;i++) ans^=1ll*i*f[i]; 41 printf("%lld",ans); 42 return 0; 43 }
CF908D
据yjc说是NOIP前留的题,然而我并不会,wsl
设$dp[i][j]$表示前缀中有i个a和j个ab的期望,在i+j>=k时到达边界,用高中数学讲的 等差数列*等比数列 算一算
答案是dp[1][0],因为dp[0][0]在没有a的时候会自己转移自己
代码咕咕了
CF908H
调了一下午,不知道为啥过不去,重构了一遍好了。。。。。。
先把AND的连起来,然后一个联通块里XOR判无解,剩下的XOR连边之后相当于选不相交独立集并起来,DP+容斥到有方案就输出
注意不用管siz=1的
1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 #include<algorithm> 5 #define vint vector<int> 6 #define vit vector<int> ::iterator 7 using namespace std; 8 const int N=50,M=(1<<24)+24,mod=998244353; 9 int n,m,aset[N],siz[N],idx[N],sta[N],bit[M],pw[M],dp[M]; char str[N][N]; 10 int Finda(int x) 11 { 12 return x==aset[x]?x:aset[x]=Finda(aset[x]); 13 } 14 int main() 15 { 16 scanf("%d",&n); 17 for(int i=1;i<=n;i++) 18 scanf("%s",str[i]+1),aset[i]=i,siz[i]=1; 19 for(int i=1;i<=n;i++) 20 for(int j=i+1;j<=n;j++) 21 if(str[i][j]=='A') 22 { 23 int fx=Finda(i),fy=Finda(j); 24 if(fx!=fy) aset[fy]=fx,siz[fx]+=siz[fy]; 25 } 26 memset(idx,-1,sizeof idx); 27 for(int i=1;i<=n;i++) 28 if(Finda(i)==i&&siz[i]>1) idx[i]=m++; 29 for(int i=0;i<m;i++) sta[i]|=1<<i; 30 for(int i=1;i<=n;i++) 31 for(int j=i+1;j<=n;j++) 32 if(str[i][j]=='X') 33 { 34 int fx=Finda(i),fy=Finda(j); 35 if(fx==fy) printf("-1"),exit(0); 36 if(~idx[fx]&&~idx[fy]) 37 { 38 sta[idx[fx]]|=1<<idx[fy]; 39 sta[idx[fy]]|=1<<idx[fx]; 40 } 41 } 42 dp[0]=1; int all=(1<<m)-1; 43 for(int i=1;i<=all;i++) 44 { 45 int lbt=i&-i; 46 bit[i]=bit[i>>1]+(i&1); 47 dp[i]=(dp[i^lbt]+dp[i^(sta[(int)log2(lbt)]&i)])%mod; 48 } 49 for(int i=0;i<=all;i++) pw[i]=1; 50 for(int i=0;i<=n;i++) 51 { 52 int tmp=0; 53 for(int j=all;~j;j--) 54 { 55 if((m-bit[j])&1) (tmp+=mod-pw[j])%=mod; 56 else (tmp+=pw[j])%=mod; 57 pw[j]=1ll*pw[j]*dp[j]%mod; 58 } 59 if(tmp) printf("%d",n-1+i),exit(0); 60 } 61 return 0; 62 }
CF1140
肥肠爆芡,因为沙茶博主看不懂E和之后的题解,这场比赛咕了