• 20190226


    T1:

    内存限制:32 MiB
    时间限制:2000 ms
    Luka 是一个画商,现在有 NNN 个顾客过来给她买画。每个顾客只能买彩画或者水墨画中的一种,并且每个人最多可以买 aia_iai 幅彩画或 bib_ibi 幅水墨画(每个顾客至少要买一副画)。
    为了让 Luka 高兴,至少要有 CCC 人买彩画。由于每个顾客不断地修改购买需求, Luka 请你帮忙计算对于每次修改后,有多少种不同的方案使得 Luka 高兴。
    1≤N,Q≤105,1≤C≤20,1≤ai,bi≤1091 leq N,Q leq 10^5 , 1 leq C leq 20,1 leq a_i,b_i leq 10^91N,Q105,1C20,1ai,bi109

    题解

    我们可以先算出所有买画的情况数,即为 ∏i=1n(ai+bi)prod_{i=1}^n(a_i+b_i)i=1n(ai+bi)
    考虑小于 ccc 的情况如何计算
    可以得到一个很简单的 dpdpdp 式子
    Fi,jF_{i,j}Fi,j 表示前 iii 个人, jjj 个人买了彩画的方案数
    Fi,j=Fi−1,j×bi+Fi−1,j−1×aiF_{i,j}=F_{i-1,j} imes b_i+F_{i-1,j-1} imes a_iFi,j=Fi1,j×bi+Fi1,j1×ai
    然后将其对应到线段树上的一段区间,变成这一段区间内, jjj人选了彩画的方案数
    类似一个卷积的形式,可以在 O(nlognc2)O(nlognc^2)O(nlognc2) 内得到答案
    貌似有撤销 dpdpdp 的做法(%pjd szm,可惜我不会就不写啦

    #include <cstdio>
    using namespace std;
    const int P=1e4+7,N=1e5+1;
    int n,c,b[N],a[N],h[400001],pi[400001],q;
    short g[400001][20];
    #define Ls k<<1
    #define Rs k<<1|1
    #define mid ((l+r)>>1)
    void build(int k,int l,int r){
    	if (l==r){
    		h[k]=1;g[k][0]=(short)b[l];
    		g[k][1]=(short)a[l];
    		pi[k]=a[l]+b[l];
    		if (pi[k]>=P) pi[k]-=P;
    		return;
    	}
    	build(Ls,l,mid);build(Rs,mid+1,r);
    	for (int i=0;i<=h[Ls] && i<c;i++)
    		for (int j=0;j<=h[Rs] && i+j<c;j++){
    			g[k][i+j]=((int)g[k][i+j]+(int)g[Ls][i]*(int)g[Rs][j]%P)%P;
    			if (i+j>h[k]) h[k]=i+j;
    		}
    	pi[k]=pi[Ls]*pi[Rs]%P;
    }
    void update(int k,int l,int r,int x){
    	if (l==r){
    		g[k][0]=(short)b[l];
    		g[k][1]=(short)a[l];
    		pi[k]=a[l]+b[l];
    		if (pi[k]>=P) pi[k]-=P;
    		return;
    	}
    	if (mid>=x) update(Ls,l,mid,x);
    	else update(Rs,mid+1,r,x);
    	for (int i=0;i<=h[k];i++) g[k][i]=0;
    	for (int i=0;i<=h[Ls] && i<c;i++)
    		for (int j=0;j<=h[Rs] && i+j<c;j++)
    			g[k][i+j]=((int)g[k][i+j]+(int)g[Ls][i]*(int)g[Rs][j]%P)%P;
    	pi[k]=pi[Ls]*pi[Rs]%P;
    }
    int main(){
    	scanf("%d%d",&n,&c);
    	for (int i=1;i<=n;i++)
    		scanf("%d",&a[i]),a[i]%=P;
    	for (int i=1;i<=n;i++)
    		scanf("%d",&b[i]),b[i]%=P;
    	build(1,1,n);scanf("%d",&q);
    	for (int i,sum;q--;){
    		scanf("%d",&i);
    		scanf("%d%d",&a[i],&b[i]);
    		a[i]%=P;b[i]%=P;update(1,1,n,i);
    		sum=pi[1];
    		for (int j=0;j<c;j++){
    			sum=sum-(int)g[1][j];
    			if (sum<0) sum+=P;
    		}
    		printf("%d
    ",sum);
    	}
    	return 0;
    }
    

    T2

    内存限制:256 MiB
    时间限制:1000 ms
    恶梦是一个登山爱好者,今天他来到了黄山。
    俗话说的好,不走回头路。所以在黄山,你只能往前走,或者往上走。并且很显然的是,当你走到山脊的时候,你不能够往上走,你只能往前走一步再往上走。
    抽象一点而言就是,你可以把黄山视为一个 N×NN imes NN×N 格点图,恶梦从 (0,0)(0,0)(0,0) 开始出发,要走到 (N,N)(N,N)(N,N) 。当他走到位置 (x,y)(x,y)(x,y) 的时候,它可以往 (x+1,y)(x + 1,y)(x+1,y),或 (x,y+1)(x,y+1)(x,y+1) 走。
    并且当他走到 (x,x)(x,x)(x,x) 的时候,由于他已经处在了山脊上,所以他不能够往 (x,x+1)(x,x+1)(x,x+1) 方向上走。
    当恶梦兴致勃勃准备开始爬山的时候,他的同伴告诉他,黄山由于年久失修,有一些位置出现了大坑,不能走。恶梦觉得更刺激了,但他想先知道他能有多少种方式走到黄山顶。
    由于这个数字很大,所以你只需要将答案对 109+710^9+7109+7 取模输出即可。
    N≤105,C≤103N leq 10^5,C leq 10^3N105,C103

    题解

    有点像流浪者那一题,不知道为什么并没有想出来(我太弱了
    先不考虑不超过直线 y=xy=xy=x 的限制的做法
    先把坑按照 xxx 排序,为了后续方便,我们将 (n,n)(n,n)(n,n) 也看成一个坑
    FiF_iFi 表示前面没经过坑,到达第 iii 个坑的方案数
    首先我们现将 (0,0)→(xi,yi)(0,0) ightarrow(x_i,y_i)(0,0)(xi,yi) 的方案数求出,即为 Cxi+yixiC_{x_i+y_i}^{x_i}Cxi+yixi
    然后我们扣除不合法的方案,枚举前面的坑,设不合法的路径碰到第一个坑为j
    那之后再怎么走也是不合法的(碰到坑了,所以要扣除 Fj∗Cxi+yi−xj+yjxi−xjF_j*C_{x_i+y_i-x_j+y_j}^{x_i-x_j}FjCxi+yixj+yjxixj
    考虑限制,发现所有不合法的限制得路径上的点一定会经过直线 y=x+1y=x+1y=x+1
    所以我们发现 (x1,y1)→(x2,y2)(x1,y1) ightarrow(x2,y2)(x1,y1)(x2,y2) ,不合法的部分等同于 (y1−1,x1+1)→(x2,y2)(y1-1,x1+1) ightarrow(x2,y2)(y11,x1+1)(x2,y2) 的路径数

    #include <bits/stdc++.h>
    using namespace std;
    const int N=1005,X=2e5+5,P=1e9+7;
    int n,m,f[N],jc[X],ny[X];
    struct O{int x,y;}p[N];
    inline bool M(O A,O B){
    	return A.x<B.x || A.x==B.x && A.y<B.y;
    }
    inline int C(int x,int y){
    	return 1ll*jc[x]*ny[y]%P*ny[x-y]%P;
    }
    inline int J(int X1,int Y1,int X2,int Y2){
    	int x=X2-X1,y=Y2-Y1;
    	if (x<0 || y<0) return 0;
    	return C(x+y,x);
    }
    inline int L(int X1,int Y1,int X2,int Y2){
    	return (J(X1,Y1,X2,Y2)-J(Y1-1,X1+1,X2,Y2)+P)%P;
    }
    int main(){
    	scanf("%d%d",&n,&m);jc[0]=ny[n+n]=1;
    	for (int i=1;i<=n+n;i++) jc[i]=1ll*i*jc[i-1]%P;
    	for (int x=jc[n+n],y=P-2;y;x=1ll*x*x%P,y>>=1)
    		if (y&1) ny[n+n]=1ll*ny[n+n]*x%P;
    	for (int i=n+n;i;i--) ny[i-1]=1ll*i*ny[i]%P;
    	for (int i=1;i<=m;i++) scanf("%d%d",&p[i].x,&p[i].y);
    	p[++m]=(O){n,n};sort(p+1,p+m+1,M);f[0]=-1;
    	for (int i=1;i<=m;i++) for (int j=0;j<i;j++)
    		f[i]=(f[i]-1ll*f[j]*L(p[j].x,p[j].y,p[i].x,p[i].y)%P+P)%P;
    	return printf("%d
    ",f[m]),0;
    }
    

    T3

    内存限制:512 MiB
    时间限制:1000 ms
    作为钦钦草原最绿的男人,杨某针每天都要开车巡视钦钦草原一圈。
    钦钦草原由 nnn 个城市组成, mmm 条双向道路连接着它们。经过第 iii 条道路要花费的时间是 2i2^i2i
    杨某针想要经过每条道路至少一次,在此基础上他想最小化他花费的时间。但作为曾经 CTSC 的 Cu 选手,他并不能很快地计算出这个问题。所以他向你求助。
    n≤4×105,m≤5×105n leq 4 imes 10^5,m leq 5 imes 10^5n4×105,m5×105

    题解

    每条边不会经过三次,所以一条边只会经过一次或两次
    这题要经过一个欧拉回路,所以如果一个点是奇点的话,我们要为其加上边
    那要从哪里选边呢?我们可以建最小生成树,因为如果考虑当前边 (x,y)(x,y)(x,y) ,如果 xxxyyy 在同一联通块内,那我们可以选择 x→yx ightarrow yxy路径上的边,这样总权值会比这单条边来的更小
    所以建完最小生成树,从叶子节点到根,如果当前点是奇点,那其上面那条边要选

    #include <cstdio>
    const int P=1e9+7,N=4e5+5;bool d[N];
    int n,m,pi=1,ans,head[N],V[N*2],W[N*2],nex[N*2],t,f[N];
    int get(int x){return f[x]==x?x:f[x]=get(f[x]);}
    void add(int u,int v,int w){
    	V[++t]=v;nex[t]=head[u];head[u]=t;W[t]=w;
    }
    void dfs(int x,int fa){
    	for (int i=head[x];i;i=nex[i]) if (V[i]!=fa){
    		dfs(V[i],x);
    		if (d[V[i]]) (ans+=W[i])%=P,d[x]^=1;
    	}
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++) f[i]=i;
    	for (int x,y,X,Y,i=1;i<=m;i++){
    		scanf("%d%d",&x,&y);(pi+=pi)%=P;
    		(ans+=pi)%=P;d[x]^=1;d[y]^=1;
    		if ((X=get(x))!=(Y=get(y)))
    			f[Y]=X,add(x,y,pi),add(y,x,pi);
    	}
    	return dfs(1,0),printf("%d
    ",ans),0;
    }
    
  • 相关阅读:
    又玩起了“数独”
    WebService应用:音乐站图片上传
    大家都来DIY自己的Blog啦
    CSS导圆角,不过这个代码没有怎么看懂,与一般的HTML是不同
    网站PR值
    CommunityServer2.0何去何从?
    网络最经典命令行
    炎热八月,小心"落雪"
    Topology activation failed. Each partition must have at least one index component from the previous topology in the new topology, in the same host.
    SharePoint 2013服务器场设计的一些链接
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/10544699.html
Copyright © 2020-2023  润新知