先给出ydc的题解地址:
http://ydc.blog.uoj.ac/blog/336
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
const LL INF=1e16;
const int SIZEN=2010;
int N,K;
LL F[SIZEN][SIZEN];
vector > 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=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
#include
#include
#include
#include
#include
#include
#include
#include
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=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
#include
#include
#include
#include
#include
#include
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 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=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>i)&1) P[s]+=P[s^(1<
假设P数组一开始是读进来的概率数组(P[i]代表选择i的概率),那么在进行这一操作后,P[i]就成为了选择i的所有子集的概率之和。
#include
#include
#include
#include
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<>1]+(s&1);
}
memcpy(F,P,sizeof(F));
for(int i=0;i
#include
#include
#include
#include
#include
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>=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