@happyforever
2018-10-31T11:21:21.000000Z
字数 12674
阅读 544
解题报告 清北学堂
期望得分:
实际得分:
今天撞题了,所以又加了一道附加题

/**/#include <cstdio>#include <cstring>const int N=100005;char s[N];int a[N];/*void dfs(int now){long long emp=sum[now-1];for(;s[now] && sum[now]-emp<=x;++now);// printf("%d ",sum[now]);if(!s[now]){if(sum[now-1]-emp==x)flag=true;return ;}// puts("");if(sum[now-1]-emp==x)dfs(now);}*//*void bfs(int now){long long emp;while(true){emp=sum[now-1];for(;s[now] && sum[now]-emp<=x;++now);if(!s[now]){if(sum[now-1]-emp==x)flag=true;return ;}if(sum[now-1]-emp!=x)return ;}}*/int main(){freopen("divide.in","r",stdin);freopen("divide.out","w",stdout);int T,len;scanf("%d",&T);while(T--){scanf("%s",s);len=strlen(s+1);long long sum=0;bool flag=false;for(int i=0;i<len;++i)a[i+1]=s[i]-'0',sum+=a[i+1];for(int i=2;i<=len;++i){int tom=0,t=0,p;if(sum%i==0){p=sum/i;for(int j=1;j<=len;++j){if(tom+a[j]<p){tom+=a[j];continue;}elseif(tom+a[j]==p){tom=0;++t;continue;}elseif(tom+a[j]>p)break;}if(tom==0&&t==i){flag=true;break;}}}puts(flag?"YES":"NO");}fclose(stdin);fclose(stdout);return 0;}

#include<cstdio>int n;const int ans[]={0,1,1,4,38,728,26704,1866256,251548592,412163774,158488195,768116971,789817415};int main(){freopen("count.in","r",stdin);freopen("count.out","w",stdout);scanf("%d",&n);if(n<=9)printf("%d",ans[n]);else printf("baka!\nbzoj 3456 chengshiguihua");fclose(stdin); fclose(stdout);return 0;}

#include <iostream>#include <cstring>#include <cstdio>const int M=100005;long long ans;int n,m,tot;int x[M],y[M],c[M],num[M];int to[M*2],net[M*2],head[M];int top[M],size[M],dad[M],deep[M],length[M];inline int read(){int n=0,w=1;register char c=getchar();while(c<'0' || c>'9'){if(c=='-')w=-1;c=getchar();}while(c>='0' && c<='9')n=n*10+c-'0',c=getchar();return n*w;}void add(int v,int u){to[++tot]=v;net[tot]=head[u];head[u]=tot;//cap[tot]=w;to[++tot]=u;net[tot]=head[v];head[v]=tot;//cap[tot]=w;}inline int max(int x,int y){return x>y?x:y;}void dfs(int now){size[now]=1;deep[now]=deep[dad[now]]+1;for(int i=head[now];i;i=net[i])if(to[i]!=dad[now]){dad[to[i]]=now;length[to[i]]=length[now]+c[to[i]];dfs(to[i]);size[now]+=size[to[i]];}}void dfsl(int now){int t=0;if(!top[now])top[now]=now;for(int i=head[now];i;i=net[i])if(to[i]!=dad[now] && size[to[i]]>size[t])t=to[i];if(t){top[t]=top[now];dfsl(t);}for(int i=head[now];i;i=net[i])if(to[i]!=dad[now] && t!=to[i])dfsl(to[i]);}int lca(int x,int y){while(top[x]!=top[y]){if(deep[top[x]]<deep[top[y]])std::swap(x,y);x=dad[top[x]];}return deep[x]>deep[y]?y:x;}bool judge(int qwq){for(int i=1;i<=qwq;++i)for(int j=i+1;j<=qwq;++j){int a=x[i],b=y[i],c=x[j],d=y[j];int S=lca(a,b);int T=lca(c,d);if(deep[S]<deep[T]){std::swap(S,T);std::swap(a,c);std::swap(b,d);}if(lca(S,c)==S||lca(S,d)==S)return false;}return true;}void dfsans(int now,int qwq){if(now>m){long long sum=0;if(qwq==1){int tmp=lca(x[num[1]],y[num[1]]);sum+=length[x[num[1]]]+length[y[num[1]]]-2*length[tmp]+c[tmp];ans=max(ans,sum);}elseif(qwq>1 && judge(qwq)){for(int i=1;i<=qwq;++i)sum+=length[x[i]]+length[y[i]]-2*length[lca(x[i],y[i])]+c[lca(x[i],y[i])];ans=max(ans,sum);}return ;}num[qwq+1]=now;dfsans(now+1,qwq+1);num[qwq+1]=0;dfsans(now+1,qwq);}int main(){freopen("max.in","r",stdin);freopen("max.out","w",stdout);scanf("%d",&n);for(int i=1;i<=n;++i)scanf("%d",&c[i]);for(int i=1;i<n;++i)add(read(),read());length[1]=c[1];dfs(1);dfsl(1);scanf("%d",&m);for(int i=1;i<=m;++i)scanf("%d%d",&x[i],&y[i]);dfsans(1,0);printf("%d",ans);fclose(stdin);fclose(stdout);return 0;}

/**/#include <cstdio>const int N=33;int n,m,a[N],b[N],ans;inline int max(int x,int y){return x>y?x:y;}void dfs(int now,int sum,int tot){if(tot<=m)ans=max(ans,sum);if(now>n)return ;dfs(now+1,sum,tot);dfs(now+1,sum+b[now],tot^a[now]);}int main(){freopen("xor.in","r",stdin);freopen("xor.out","w",stdout);scanf("%d%d",&n,&m);for(int i=1;i<=n;++i)scanf("%d%d",&a[i],&b[i]);dfs(1,0,0);printf("%d",ans);fclose(stdin);fclose(stdout);return 0;}
枚举将整个串分成几个部分,而后就可以求出每个部分的总和是多少(也就是划分成的每个部分的“相等”的和是多少),维护前缀和检查和的倍数是否出现。可以开bool数组,查询。
#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<string>#include<cmath>#include<cstdlib>#include<ctime>using namespace std;typedef long long ll;typedef long double ld;typedef pair<int,int> pr;const double pi=acos(-1);#define rep(i,a,n) for(int i=a;i<=n;i++)#define per(i,n,a) for(int i=n;i>=a;i--)#define Rep(i,u) for(int i=head[u];i;i=Next[i])#define clr(a) memset(a,0,sizeof a)#define pb push_back#define mp make_pairld eps=1e-9;ll pp=1000000007;ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}ll read(){ll ans=0;char last=' ',ch=getchar();while(ch<'0' || ch>'9')last=ch,ch=getchar();while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();if(last=='-')ans=-ans;return ans;}//head#define N 110000char str[N];bool a[N*9];int main(){freopen("divide.in","r",stdin);freopen("divide.out","w",stdout);int T=read();while(T--){scanf("%s",str);int n=strlen(str);rep(i,0,9*n)a[i]=0;int t=0;a[t]=1;rep(i,0,n-1){t+=str[i]-'0';a[t]=1;}if(t==0){puts("YES");continue;}bool ans=0;rep(i,2,n)if(t%i==0){int pf=1;int siz=t/i;for(int j=siz;j<=t;j+=siz)if(!a[j]){pf=0;break;}if(pf){ans=1;break;}}if(ans)puts("YES");else puts("NO");}return 0;}
都可以通过打表解决
的部分分可以选择表示有个点的图的合法的方案数有多少。枚举所在的联通块的大小,找剩余的点,就是一个不合法的情况。总数是
分算法则是。。。
这也就是为啥会有的部分分,最后分纯粹是为了让某些同学装用的
#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>using namespace std;typedef long long ll;typedef long double ld;typedef pair<int,int> pr;const double pi=acos(-1);#define rep(i,a,n) for(int i=a;i<=n;i++)#define per(i,n,a) for(int i=n;i>=a;i--)#define Rep(i,u) for(int i=head[u];i;i=Next[i])#define clr(a) memset(a,0,sizeof a)#define pb push_back#define mp make_pairld eps=1e-9;ll pp=998244353;ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}ll read(){ll ans=0;char last=' ',ch=getchar();while(ch<'0' || ch>'9')last=ch,ch=getchar();while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();if(last=='-')ans=-ans;return ans;}//head#define N 310000ll f[N],b1[N],b2[N],inv[N],f2[N],b[N],tt[N],e[N],recf[N],recb[N],Sum[N];int bel[N];int n;ll C(int n,int m){if(n<m)return 0;if(m==0 || n==m)return 1;return b[n]*inv[n-m]%pp*inv[m]%pp;}void fnt(ll *a,int n,int fl){for(int i=n>>1,j=1;j<n;j++){if(i<j)swap(a[i],a[j]);int k=n>>1;for(;k&i;i^=k,k>>=1);i^=k;}ll g=powmod(3,(pp-1)/n,pp);if(fl==-1)g=powmod(g,n-1,pp);e[0]=1;for(int i=1;i<n;i++)e[i]=mo(e[i-1]*g,pp);for(int m=2,t=n>>1;m<=n;m<<=1,t>>=1)for(int i=0;i<n;i+=m)for(int j=i;j<i+(m>>1);j++){ll u=a[j],v=mo(a[j+(m>>1)]*e[(j-i)*t],pp);a[j]=u+v;if(a[j]>=pp)a[j]-=pp;a[j+(m>>1)]=u-v;if(a[j+(m>>1)]<0)a[j+(m>>1)]+=pp;}}void Add(ll &a,ll b){a+=b;if(a>=pp)a-=pp;}int get(){return (rand()<<10)+rand();}int main(){freopen("count.in","r",stdin);freopen("count.out","w",stdout);n=read();b[0]=inv[0]=1;rep(i,1,n)b[i]=b[i-1]*i%pp,inv[i]=powmod(b[i],pp-2,pp);f[1]=f2[1]=1;rep(i,1,n)b1[i]=powmod(2,C(i,2),pp);rep(i,1,n)b2[i]=b1[i]*inv[i]%pp;int nn=256,n2=nn*2;rep(i,1,n)bel[i]=i/nn;int num=0;ll t=powmod(nn*2,pp-2,pp);rep(i,1,n){if(i%nn==0){rep(j,0,nn*2)tt[j]=0;rep(j,1,bel[i]-1){int t1=j*n2,t2=(bel[i]-j)*n2;rep(k,0,nn*2-1)tt[k]=(tt[k]+recf[t1+k]*recb[t2+k])%pp;}fnt(tt,nn*2,-1);rep(j,0,nn*2-1)Sum[bel[i]*nn+j]=(Sum[bel[i]*nn+j]+tt[j]*t)%pp;}f[i]=mo(b1[i]-Sum[i]*b[i-1],pp);f2[i]=f[i]*inv[i-1]%pp;for(int j=1;j<i && j<nn;j++)Sum[i+j]=(Sum[i+j]+f2[j]*b2[i]+f2[i]*b2[j])%pp;if(i<nn)Add(Sum[i+i],f2[i]*b2[i]%pp);if(i%nn==nn-1){rep(j,0,nn*2)tt[j]=0;rep(j,bel[i]*nn,i)tt[j%nn]=f2[j];fnt(tt,nn*2,1);rep(j,0,nn*2-1)recf[bel[i]*n2+j]=tt[j];rep(j,0,nn*2)tt[j]=0;rep(j,bel[i]*nn,i)tt[j%nn]=b2[j];fnt(tt,nn*2,1);rep(j,0,nn*2-1)recb[bel[i]*n2+j]=tt[j];}}cout<<f[n]<<endl;return 0;}
表示以为根的子树里面,答案最大可能是多少(只考虑子树中的路径覆盖子树的情况)
那么有
如果一个树根被覆盖了,就用其他未被覆盖的值加上被覆盖的边的边权。
因为树是随机的,所以深度不会太深。表示节点所有的儿子的值的和减去它本身的值。相当于只要考虑覆盖了根节点的路径的值之和和路径长就可以了
总复杂度就可以是
#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>using namespace std;typedef long long ll;typedef long double ld;typedef pair<int,int> pr;const double pi=acos(-1);#define rep(i,a,n) for(int i=a;i<=n;i++)#define per(i,n,a) for(int i=n;i>=a;i--)#define Rep(i,u) for(int i=head[u];i;i=Next[i])#define clr(a) memset(a,0,sizeof a)#define pb push_back#define mp make_pairld eps=1e-9;ll pp=1000000007;ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}ll read(){ll ans=0;char last=' ',ch=getchar();while(ch<'0' || ch>'9')last=ch,ch=getchar();while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();if(last=='-')ans=-ans;return ans;}//head#define N 210000int head[N],v[N],Next[N],dep[N],fa[N][18],a[N],st[N],ed[N];int n,num,m,num2,num3,nn,head2[N],v2[N],Next2[N];int lson[N],rson[N],root=0;ll Sum,f[N],s[N][2],sa[N];struct node{int x,y,z;}q[N];void add(int x,int y){v[++num]=y;Next[num]=head[x];head[x]=num;}void add2(int x,int y){v2[++num2]=y;Next2[num2]=head2[x];head2[x]=num2;}int Q[N],siz[N];void dfs(int u){int t=0,w=1;Q[1]=u;while(t<w){u=Q[++t];sa[u]=sa[fa[u][0]]+a[u];for(int i=1;(1<<i)<=dep[u];i++)fa[u][i]=fa[fa[u][i-1]][i-1];for(int i=head[u];i;i=Next[i])if(v[i]!=fa[u][0]){fa[v[i]][0]=u;dep[v[i]]=dep[u]+1;Q[++w]=v[i];}siz[u]=1;}per(i,w,2)siz[fa[Q[i]][0]]+=siz[Q[i]];st[1]=1;rep(i,1,n){u=Q[i];int t=st[u];ed[u]=st[u]+siz[u]-1;for(int i=head[u];i;i=Next[i])if(v[i]!=fa[u][0])st[v[i]]=t+1,t+=siz[v[i]];}}int lca(int x,int y){if(dep[x]<dep[y])swap(x,y);per(i,17,0)if(dep[x]-(1<<i)>=dep[y])x=fa[x][i];if(x==y)return x;per(i,17,0)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];return fa[x][0];}int lca2(int x,int y){per(i,17,0)if(dep[x]-(1<<i)>dep[y])x=fa[x][i];return x;}void change(int &u,int l,int r,int x,int y,ll w,int k){if(x>r || y<l)return ;if(!u)u=++num3;if(x<=l && y>=r){s[u][k]+=w;return;}int mid=(l+r)>>1;change(lson[u],l,mid,x,y,w,k);change(rson[u],mid+1,r,x,y,w,k);}ll find(int u,int l,int r,int x,int k){if(!x)return 0;if(!u)return 0;if(l==r)return s[u][k];int mid=(l+r)>>1;if(x<=mid)return find(lson[u],l,mid,x,k)+s[u][k];else return find(rson[u],mid+1,r,x,k)+s[u][k];}ll work2(int x,int y){return find(root,1,n,st[x],1)-find(root,1,n,st[fa[y][0]],1)-(find(root,1,n,st[x],0)-find(root,1,n,st[y],0));}ll work(int x,int y,int z){if(dep[x]<dep[y])swap(x,y);if(y==z)return work2(x,y)+sa[x]-sa[fa[y][0]];int t=lca2(y,z);return work2(x,z)+work2(y,t)-f[t]+sa[x]+sa[y]-sa[z]-sa[fa[z][0]];}void dfs2(int u){per(i,n,1){u=Q[i];f[u]=0;for(int i=head[u];i;i=Next[i])if(v[i]!=fa[u][0])f[u]+=f[v[i]];for(int i=head2[u];i;i=Next2[i]){int t=v2[i];int x=q[t].x,y=q[t].y,z=q[t].z;f[u]=max(f[u],work(x,y,z));}change(root,1,n,st[u],ed[u],f[u],0);change(root,1,n,st[fa[u][0]],ed[fa[u][0]],f[u],1);}}int main(){freopen("max.in","r",stdin);freopen("max.out","w",stdout);n=read();rep(i,1,n)a[i]=read();rep(i,2,n){int x=read(),y=read();add(x,y);add(y,x);}dfs(1);m=read();rep(i,1,m)q[i].x=read(),q[i].y=read(),q[i].z=lca(q[i].x,q[i].y),add2(q[i].z,i);dfs2(1);cout<<f[1]<<endl;return 0;}
meet in the middle 左右两边各有种可能。从左右两边各挑选一个,使得其和小于且最大。
对所有左边所有的情况建01-trie树,对于右边的找其与左边所有的组合,最优的是多少。
若的最高位是,的最高位与trie树的某子树的为,那这个子树所有组合都是小于的,预处理出所有子树中的最大和,更新答案。
#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<set>using namespace std;typedef long long ll;typedef long double ld;typedef pair<int,int> pr;const double pi=acos(-1);#define rep(i,a,n) for(int i=a;i<=n;++i)#define per(i,n,a) for(int i=n;i>=a;--i)#define Rep(i,u) for(int i=head[u];i;i=Next[i])#define clr(a) memset(a,0,sizeof a)#define pb push_back#define mp make_pair#define fi first#define sc secondld eps=1e-9;ll pp=1000000007;ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}ll read(){ll ans=0;char last=' ',ch=getchar();while(ch<'0' || ch>'9')last=ch,ch=getchar();while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();if(last=='-')ans=-ans;return ans;}//headint nn=1,ans=0,n,m,tot=0;int son[2000000][2],Max[2000000];int a[50],b[50];void insert(int x,int s){int t=1;per(i,29,0){int kk=(x>>i)&1;if(!son[t][kk])son[t][kk]=++nn;t=son[t][kk];Max[t]=max(Max[t],s);}}void query(int u,int dep,int x,int s){if(!u)return;if(dep==-1)return;int kk=((x>>dep)&1)^((m>>dep)&1);if(((m>>dep)&1)==1)ans=max(ans,s+Max[son[u][kk^1]]);query(son[u][kk],dep-1,x,s);}void dfs1(int t1,int t2,int x,int s){if(t1>t2){tot+=1;insert(x,s);return;}dfs1(t1+1,t2,x,s);dfs1(t1+1,t2,x^a[t1],s+b[t1]);}void dfs2(int t1,int t2,int x,int s){if(t1>t2){query(1,29,x,s);return;}dfs2(t1+1,t2,x,s);dfs2(t1+1,t2,x^a[t1],s+b[t1]);}int main(){freopen("xor.in","r",stdin);freopen("xor.out","w",stdout);n=read();m=read();m+=1;int ss=0;rep(i,1,n)a[i]=read(),b[i]=read(),ss+=b[i];dfs1(1,n/2,0,0);dfs2(n/2+1,n,0,0);cout<<ans<<endl;return 0;}