先给出ydc的题解地址:
http://ydc.blog.uoj.ac/blog/336
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> using namespace std; typedef long long LL; const LL INF=1e16; const int SIZEN=2010; int N,K; LL F[SIZEN][SIZEN]; vector<pair<int,int> > c[SIZEN]; int subsz[SIZEN]; void DFS(int x,int fa){ F[x][0]=F[x][1]=0; subsz[x]=1; for(int i=0;i<c[x].size();i++){ int u=c[x][i].first; if(u==fa) continue; DFS(u,x); subsz[x]+=subsz[u]; for(int j=subsz[x];j>=0;j--){ for(int k=0;k<=subsz[u]&&k<=j;k++){ LL add=(LL)k*(K-k)+(LL)(subsz[u]-k)*(N-K-(subsz[u]-k)); add*=c[x][i].second; add+=F[u][k]; F[x][j]=max(F[x][j],F[x][j-k]+add); } } } } void read(void){ scanf("%d%d",&N,&K); int a,b,w; for(int i=1;i<N;i++){ scanf("%d%d%d",&a,&b,&w); c[a].push_back(make_pair(b,w)); c[b].push_back(make_pair(a,w)); } } int main(){ freopen("haoi2015_t1.in","r",stdin); freopen("haoi2015_t1.out","w",stdout); read(); for(int i=0;i<SIZEN;i++) for(int j=0;j<SIZEN;j++) F[i][j]=-INF; DFS(1,0); cout<<F[1][K]<<endl; return 0; }
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<cstdlib> #include<iomanip> #include<vector> using namespace std; typedef long long LL; const int SIZEN=100010,SIZEM=200010; int N,M; class Edge{ public: int to; int nxt; }; Edge edges[SIZEM]; int tot=0; int head[SIZEN]; LL val[SIZEN]; LL lis_val[SIZEN]; int father[SIZEN]; int lis_fa[SIZEN]; int subsz[SIZEN]; int dfn[SIZEN]; int dfslis[SIZEN]; int timer=0; int BN,Bsize; int start[SIZEN],end[SIZEN]; int belong[SIZEN]; LL badd[SIZEN];//整个区间被加了多少 LL cgoal[SIZEN];//跳出块之前最后跳到哪里 LL cnum[SIZEN];//跳出块之前有多少个 LL csum[SIZEN];//跳出块之前的和(不计badd) void calc_block(int k){ for(int i=start[k];i<=end[k];i++) lis_val[i]+=badd[k]; badd[k]=0; for(int i=start[k];i<=end[k];i++){ int j=lis_fa[i]; if(belong[j]!=k){ cgoal[i]=i; cnum[i]=1; csum[i]=lis_val[i]; } else{ cgoal[i]=cgoal[j]; cnum[i]=cnum[j]+1; csum[i]=csum[j]+lis_val[i]; } } } void seg_add(int l,int r,LL w){ if(belong[l]==belong[r]){ for(int i=l;i<=r;i++){ lis_val[i]+=w; } calc_block(belong[l]); } else{ for(int k=belong[l]+1;k<belong[r];k++){ badd[k]+=w; } for(int i=l;i<=end[belong[l]];i++) lis_val[i]+=w; for(int i=start[belong[r]];i<=r;i++) lis_val[i]+=w; calc_block(belong[l]); calc_block(belong[r]); } } LL query(int u){ int k=dfn[u]; LL ans=0; while(k){ ans+=csum[k]+cnum[k]*badd[belong[k]]; k=lis_fa[cgoal[k]]; } return ans; } void work(void){ int cmd; int x,a; for(int i=1;i<=M;i++){ scanf("%d",&cmd); if(cmd==1){ scanf("%d%d",&x,&a); seg_add(dfn[x],dfn[x],a); } else if(cmd==2){ scanf("%d%d",&x,&a); seg_add(dfn[x],dfn[x]+subsz[x]-1,a); } else if(cmd==3){ scanf("%d",&x); LL ans=query(x); printf("%lld\n",ans); } } } void make_block(void){ for(int i=1;i<=N;i++){ lis_val[dfn[i]]=val[i]; lis_fa[dfn[i]]=dfn[father[i]]; } Bsize=sqrt(1.0*N)+1; BN=1;start[1]=1; int tot=0; for(int i=1;i<=N;i++){ belong[i]=BN; end[BN]=i; tot++; if(tot>=Bsize||i==N){ BN++; start[BN]=i+1; tot=0; } } for(int i=1;i<=BN;i++) calc_block(i); } void DFS(int x){ dfn[x]=++timer; dfslis[timer]=x; subsz[x]=1; for(int i=head[x];i!=-1;i=edges[i].nxt){ Edge &e=edges[i]; int u=e.to; if(u==father[x]) continue; father[u]=x; DFS(u); subsz[x]+=subsz[u]; } } void addedge(int from,int to){ edges[tot]=(Edge){to,head[from]}; head[from]=tot; tot++; } void read(void){ scanf("%d%d",&N,&M); int x; for(int i=1;i<=N;i++){ scanf("%d",&x); val[i]=x; } int a,b; for(int i=1;i<N;i++){ scanf("%d%d",&a,&b); addedge(a,b); addedge(b,a); } } int main(){ freopen("haoi2015_t2.in","r",stdin); freopen("haoi2015_t2.out","w",stdout); memset(head,-1,sizeof(head)); read(); DFS(1); make_block(); work(); return 0; }
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<cmath> using namespace std; const int SIZE=100010; class Seg{ public: int l,r; int sg; }; bool operator < (const Seg &s,int a){ return s.l>a; } vector<Seg> segs; int find_sg(int a){ int k=lower_bound(segs.begin(),segs.end(),a)-segs.begin(); return segs[k].sg; } int cur_cnt(int l,int r,int a){ return r/a-(l-1)/a; } int cur_cnt(const Seg &s,int a){ return cur_cnt(s.l,s.r,a); } Seg merge(Seg a,const Seg &b){ a.l=min(a.l,b.l); a.r=max(a.r,b.r); return a; } int vis[SIZE]={0}; int timer=0; void calc_seg(int L,int R){//保证L~R的SG值一样 //以R为例 timer++; int now=0; vis[now]=timer; for(int i=segs.size()-1;i>=0;i--){ Seg &s=segs[i]; int t=cur_cnt(s,R); if(t>=1) vis[now^s.sg]=timer; if(t&1) now^=s.sg; } int f; for(f=0;;f++){ if(vis[f]!=timer) break; } Seg s;s=(Seg){L,R,f}; if(!segs.empty()&&f==segs.back().sg) segs.back()=merge(segs.back(),s); else segs.push_back(s); } int N,K; void work(void){ int w,x,f=0; scanf("%d",&w); for(int i=1;i<=w;i++){ scanf("%d",&x); f^=find_sg(x); } if(f==0) printf("No\n"); else printf("Yes\n"); } void prepare(void){ int B=sqrt(N+0.5); for(int i=1;i<B;i++) calc_seg(N/(i+1)+1,N/i); for(int i=N/B;i>=1;i--) calc_seg(i,i); } int main(){ freopen("haoi2015_t3.in","r",stdin); freopen("haoi2015_t3.out","w",stdout); scanf("%d%d",&N,&K); prepare(); for(int i=1;i<=K;i++) work(); return 0; }ps:题解中说N=10^9时SG函数的段数不超过2000,但实际应为9000多……不过并没有这样的极限数据,所以也能过……
for(int i=0;i<N;i++){ for(int s=0;s<(1<<N);s++){ if((s>>i)&1) P[s]+=P[s^(1<<i)]; } }假设P数组一开始是读进来的概率数组(P[i]代表选择i的概率),那么在进行这一操作后,P[i]就成为了选择i的所有子集的概率之和。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const double eps=1e-10; int N; double P[1<<20]; double F[1<<20]; int cnt[1<<20]; int getdig(int s,int i){return (s>>i)&1;} void work(void){ cnt[0]=0; for(int s=1;s<(1<<N);s++){ cnt[s]=cnt[s>>1]+(s&1); } memcpy(F,P,sizeof(F)); for(int i=0;i<N;i++){ for(int s=0;s<(1<<N);s++){ if(getdig(s,i)) F[s]+=F[s^(1<<i)]; } } double ans=0; for(int s=0;s<(1<<N)-1;s++){ double p=F[s]; if(1-p<eps){ printf("INF\n"); return; } double now=1/(1-p); if((N-cnt[s])&1) ans+=now; else ans-=now; } printf("%.10lf\n",ans); } void read(void){ scanf("%d",&N); for(int i=0;i<(1<<N);i++) scanf("%lf",&P[i]); } int main(){ freopen("haoi2015_set.in","r",stdin); freopen("haoi2015_set.out","w",stdout); read(); work(); return 0; }
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long LL; const int SIZEN=510; const int MOD=998244353; int timer=0; class Matrix{ public: int n,m; int s[5][5]; inline void clear(int n_,int m_){ n=n_; m=m_; memset(s,0,sizeof(s)); } inline void unit(int x){ n=m=x; memset(s,0,sizeof(s)); for(int i=0;i<n;i++) s[i][i]=1; } inline void operator *= (const Matrix &b){ static int c[5][5]; LL now; for(int i=0;i<n;i++){ for(int j=0;j<b.m;j++){ c[i][j]=0; now=0; for(int k=0;k<m;k++){ now+=(LL)s[i][k]*b.s[k][j]; } c[i][j]=now%MOD; } } memcpy(s,c,sizeof(s)); m=b.m; } }; void print(Matrix a){ cout<<a.n<<" "<<a.m<<": "<<endl; for(int i=0;i<a.n;i++){ for(int j=0;j<a.m;j++){ cout<<a.s[i][j]<<" "; } cout<<endl; } cout<<endl; } inline Matrix operator * (const Matrix &a,const Matrix &b){ Matrix c; c.n=a.n,c.m=b.m; LL now; for(int i=0;i<c.n;i++){ for(int j=0;j<c.m;j++){ c.s[i][j]=0; now=0; for(int k=0;k<a.m;k++){ now+=(LL)a.s[i][k]*b.s[k][j]; } c.s[i][j]=now%MOD; } } return c; } inline Matrix operator + (Matrix a,const Matrix &b){ for(int i=0;i<a.n;i++){ for(int j=0;j<a.m;j++){ a.s[i][j]=(a.s[i][j]+b.s[i][j])%MOD; } } return a; } inline Matrix slowpow(Matrix a,int n){ Matrix ans; ans.unit(a.n); for(int i=1;i<=n;i++) ans*=a; return ans; } inline Matrix quickpow(Matrix a,int n){ Matrix ans; ans.unit(a.n); while(n){ if(n&1) ans*=a; a*=a; n>>=1; } return ans; } char S[510]; int L,M; Matrix step; Matrix seq[SIZEN][SIZEN]; Matrix DP[SIZEN]; int F[SIZEN]={0}; void work(void){ DP[0].unit(M); for(int i=1;i<=L;i++){ DP[i].clear(M,M); for(int k=1;k<=i;k++){ DP[i]=DP[i]+DP[i-k]*seq[i-k+1][i]; } } F[0]=1; for(int i=1;i<=M;i++){ for(int k=1;k<=M;k++){ if(i-k<0) continue; F[i]=(F[i]+F[i-k])%MOD; } } Matrix ori; ori.clear(M,1); for(int i=0;i<M;i++) ori.s[i][0]=F[i]; ori=DP[L]*ori; printf("%d\n",ori.s[0][0]); } Matrix step_pow[20]; void prepare(void){ step.clear(M,M); for(int i=0;i<M-1;i++) step.s[i][i+1]=1; for(int i=0;i<M;i++) step.s[M-1][i]=1; step_pow[0].unit(M); for(int i=1;i<20;i++) step_pow[i]=step_pow[i-1]*step; for(int i=1;i<=L;i++){ Matrix now; now.unit(M); for(int j=i;j<=L;j++){ now=quickpow(now,10)*step_pow[S[j]-'0']; seq[i][j]=now; } } } void read(void){ scanf("%s",S+1); L=strlen(S+1); scanf("%d",&M); } int main(){ freopen("haoi2015_str.in","r",stdin); freopen("haoi2015_str.out","w",stdout); read(); prepare(); work(); return 0; }