省选不杂题乱写(1)

「SDOI2017」相关分析(线段树)

给定序列xy,有三种操作:

1. 给定L,R求下式

a=i=LR(xix¯)(yiy¯)i=LR(xix¯)2

2.(两个序列分别)区间加(不同值)
3.(两个序列分别)区间修改为(S/T)+i(下标)

sol

a=i=LR(xix¯)(yiy¯)i=LR(xix¯)2=i=LR(xiyix¯yiy¯xi+x¯y¯)i=LRxi2nx¯2=i=LRxiyinx¯y¯i=LRxi2nx¯2

分别标记各个部分。

区间加的部分

(xi+S)(yi+T)=xiyi+Syi+Txi+(rl+1)ST

(xi+S)2=xi2+2Sxi+(rl+1)S2

区间修改的部分

明智的办法,西使西我们先将区间修改为下标,再加上ST

我们得知道

12+22++n2=n(n+1)(2n+1)6

由此来快速算出xi=i2+(i+1)2++(j1)2+j2=j(j+1)(2j+1)i(i1)(2i1)6


「HAOI2012」高速公路(线段树)

所求即为

E=i=lr((il+1)×(ri)+(il)×(ri+1))vi(rl+1)(rl)=i=lr(rii2lr+lii+r+rii2+ilr+lil)vi(rl+1)(rl)=i=lr(2li+2ri2i22lr+rl)vi(rl+1)(rl)=2(l+r)ivi2i2vi+(rl2lrv+i)(rl+1)(rl)

分别维护区间ivii2vivi即可。


「SHOI2014」概率充电器(树形DP,up and down,概率)

由于每个节点的价值都是1,实际上就是求通电概率和。

是个树形DP,运用传说中的up and down思想。与换根DP类似,这也是一种能够处理树上节点信息需要从与其连接各节点(也即包括了子节点与父节点)转移过来这样问题的方法。

明确一个结论:

两个相独立事件A,B,发生的概率分别为P(A),P(B)

P(A+B)=P(A)+P(B)P(A)×P(B)

或者可以说是

P(A+B)=P(A)+(1P(A))×P(B)

接下来针对节点x通电考虑这些相独立的事件:

  1. x自己通电

  2. x的某儿子(通过x的子树)通电,并且连向该儿子的边通电

  3. x的父亲(通过了x子树之外的节点)通电,并且与父亲相连的边通电

根据那啥up and down思想,可以尝试第一遍先处理12,得到只考虑这两种情况下的答案,第二遍再处理3

首先是up,根据上面那个独立事件和概率,更新时,对于节点x以及其子节点y

Px=Px+Py×p(x,y)Px×Py×p(x,y)

然后是down。对于一组xfax,真正的Pfax是已经求出的,然后要获得fax在不计算x时的答案,设这个答案为G。则:

Pfax=G+Px×p(fax,x)G×Px×p(fax,x)

G=PfaxPx×p(fax,x)1Px×p(fax,x)

需要注意的是,这里分母可能是0。这种情况下由于Px已经是1,不需要继续更新。

最后

Px=Px+Py×p(x,y)Px×Py×p(x,y)


「SDOI2010」地精部落(DP,排列)

什么妖魔鬼怪题解区,晕了....

求波动排列数。

排列的可用性质?

由于这里只涉及大小比较,我们可以只考虑一个

也就是说1 2 4的排列和1 2 3的排列是一样的捏()

并且往后排列只关心相邻两数的大小关系。于是我们可以设状态:

fi,j,0/1表示i的排列,最后一个数为j并且为山谷/峰的波动排列数。则:

fi+1,j+[1,ij],1+=fi,j,0

fi+1,j[1,j1],0+=fi,j,1

复杂度O(n3),前缀和和滚动数组优化后O(n2)

浅言一下求排列的题目特征()我自己喜欢把部分离散为相对大小,而常见的做法是加入一个新的最大数,然后考虑这个数和前面每个数交换产生的结果。


[LNOI2014] LCA(LCA,离线)

以前写过为什么现在又忘了啊()

而且也没有做法离线的敏感度了。这里大概是从查询形式是lr来看出,要么是数据结构要么是离线前缀和作差(?

[l,r]线

具体是这样的,(dep)西depxxlcaxylca更进一步地,ydeplca

查询一堆点-一个点的lca深度和,就可以变成这样一个算法:

将这堆点每个点到根节点的路径每个点权值都+1,再计算这个单点到根节点的权值和。

既然是路径修改就可以树剖辽!

但是我们每次做查询的时候肯定是将某个区间的点按照上述前半句的方式加进来,再对另外某个单点进行这样权值和的查询。

把询问(1,l1,z,qid)(1,r,z,qid)离线下来,依次修改每个点到根的路径,到点查询记录答案,做完了()


Luogu P3413 SAC#1 - 萌数(数位DP,单步容斥)(没写)

正着不好做就反着做,我连这个都忘了吗...

这个东西叫单步容斥=

使用单步容斥的可循标志是:xx一般计算不含xx的方案数更好做一点。

既然是至少长度为2的回文串,我们其实只需要考虑长度为23的。

要求不带回文串的数,我们只需要不存在aa以及aba的情况即可。转移时由于只需要考虑前两个位置,我们设fi,j,k表示有i位,最后一位为k,倒数第二位为j的无回文串数。

fi,j,k=fi1,o,j(ojk)

感觉能加矩阵..?

哦,等一下,要求的是lr的啊..


[HNOI2015]落忆枫音(DAG,DP,计数)

首先考虑这个DAG的答案。给每个节点都选一个父亲,由乘法原理:

preANS=i=1nINi

然后考虑加一条边成环

加边x>y,那么这条边会与一条y>x的路径形成一个环。当我们选择了某整个环,就会形成一个不合法方案。

我超,想了一个上午没想明白的原来是这个事情。构造一棵外向树,我只可能选择一条y>x的路径。

那么每个这样一条包含k个点的y>x路径造成的不合法方案数是:

preANSi=1kINai

这可不兴算啊(

可以把这种西

当我们在一条y>x的路径上由v>u走一步,那么经过了v的这条路径到达了u之后,这所有的路径在u这里就固定了选边,于是方案数会÷INu。设fu表示y>u所有路径固定时的不合法构造方案数,拓扑上DP,那么有:

fu=vsonufvINu

其中初始化fy=preANS。最后:

ans=preANSfx

记得


2014 湖北省队互测 week2 已经没有什么好害怕的了(DP,二项式反演)

另外一种能(PS:这题实际上并非多步容斥,而是二项式反演。形式上与多步容斥有些类似,但并非“恰好”与“至少”,而是“恰好”与“钦定”的转变。

放个yyb引用的题目:【TopCoder10697】RabbitNumbering

构造n个整数,每个数可选的区间为[1,ai],求序列构造方案数。

跟顺序没关系的话很容易想。这样一来,选择第i个数的时候,前i1个数无论怎么选,都在[1,ai]这个区间内。于是就有ans=i=1n(aii+1)

感觉理解不够,再放一道UVA1485 Permutation Counting

这玩意不大一样,这个a,b都是排列()

用我们之前遇到排列题目的做法,然后得到以下解法:

fi,j表示i个数,E值为j的方案数。

加入第i个数,如果和前面一个有E的换,,那还是j

如果和前面一个没E的换,那就j+1了。得:

fi,j=fi1,j×j+fi1,j1×(ij)

好的,回到这个题目,我们同样先排个序

易得要求n+k2ax>by两两匹配方案数。

此题与兔数做法相似的点在于,a1ai1如果匹配出了jai>bxai要匹配一个小于其的bx的方式就会减少j

难做的点在于,如果ai匹配了一组ai<bx,那么我们很难得知j>iajbx的大小关系。

那么我们就先匹配ai>bx

其实这个做法叫。具体来说:

image

Fi,j表示前i个糖果钦定了jai>bx的方案数,Pi表示小于aibx个数,那么:

Fi,j=Fi1,j+(Pi(j1)))×Fi1,j1

这是先钦定j个。再有钦定j个,其余任选的有重方案数fj

fj=(nj)!×Fn,j

最后是表示恰好i组的gi,满足:

fi=j=in(ji)gj

由二项式反演(3)柿得:

gi=j=in(1)ji(ji)fj

Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
const long long mod=(long long)(1e9+9);
#define MAXN (int)(2e3+7)
int n,k,T;
int a[MAXN],b[MAXN],P[MAXN];
long long F[MAXN][MAXN],C[MAXN][MAXN];
long long fr[MAXN];
long long f[MAXN],g;
inline void INIT() { fr[0]=1; for (int i=1;i<=n;i++) fr[i]=fr[i-1]*i%mod; }
inline void CINIT()
{
	C[0][0]=1;
	C[1][0]=C[1][1]=1;
	for (int i=2;i<=n;i++)
		for (int j=0;j<=i;j++)
			C[i][j]=(C[i-1][j]+C[i-1][(j-1)>=0?j-1:n+1])%mod;
}
inline int op(int mul) { return (mul&1)?-1:1; }
inline long long maxl(long long A,long long B) { return A>B?A:B; }
int main()
{
	scanf("%d%d",&n,&k); INIT(); CINIT();
	T=(n+k)/2;
	if ((n+k)&1) { puts("0"); return 0; }
	for (int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+n+1);
	for (int i=1;i<=n;i++) scanf("%d",&b[i]); sort(b+1,b+n+1);
		int J=0;
	for (int i=1;i<=n;i++)
	{
		while (J+1<=n&&a[i]>b[J+1]) J++;
		P[i]=J;
	}
	
//	puts("P:"); for (int i=1;i<=n;i++) printf("%d ",P[i]); puts("");
	
	F[0][0]=1;
	for (int i=1;i<=n;i++)
	{
//		F[i][0]=1;
		for (int j=0;j<=i;j++)
		{
			F[i][j]=((i==j?0:F[i-1][j])+((j>0)?(maxl(P[i]-(j-1),0)*F[i-1][j-1]%mod):0))%mod;	
//			if (i==1&&j==1) printf("----------- %d %lld %lld %lld\n",P[i]-(j-1),F[i-1][j-1],F[i][j],maxl(P[i]-(j-1),0)*F[i-1][j-1]%mod);
		}
	}
	for (int i=0;i<=n;i++) f[i]=(F[n][i]*fr[n-i])%mod;
	
//	puts("F:");
//	for (int i=0;i<=n;i++,cout<<endl)
//		for (int j=0;j<=i;j++)
//			printf("F[%d][%d]=%lld ",i,j,F[i][j]);
	
//	puts("f:"); for (int i=0;i<=n;i++) printf("%lld ",f[i]); puts("");
	
	for (int j=T;j<=n;j++)
		g=(g+op(j-T)*((C[j][T]*f[j])%mod)+mod)%mod;//,printf("::::C[%d][%d]=a%lld\n",j,T,C[j][T]);
	printf("%lld\n",g);
	return 0;
}

代码千万条,阳间第一条。三目运算不规范,猫猫调试两行泪。

bzoj 2839 集合计数(二项式反演)

同样是二项式反演的题。我先钦定交集中包含了i个元素,则:

pi=(ni)

fi=pi×(22ni1)

gi表示恰好交集大小为i的集合选择方案数,则:

fi=j=in(ji)gi

gk=i=kn(1)ikfi

Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
#define MAXN (int)(1e6+233)
const long long mod=(long long)(1e9+7);
int fac[MAXN],facv[MAXN];
int n,k;
inline long long qpow(long long A,long long B) { long long base=A,ans=1; while (B) { if (B&1) ans=ans*base%mod; base=base*base%mod; B>>=1; } return ans; }
inline long long sppow(long long A,long long B) { long long base=A,ans=1; while (B) { if (B&1) ans=ans*base%(mod-1); base=base*base%(mod-1); B>>=1; } return ans; }
inline long long optpow(int B) { return (B&1)?-1:1; }
inline void INIT() { fac[0]=1; for (int i=1;i<=n;i++)  fac[i]=(int)((fac[i-1]*1ll*i)%mod); facv[n]=(int)(qpow(fac[n],mod-2)%mod); for (int i=n-1;i>=0;i--) facv[i]=(int)((facv[i+1]*1ll*(i+1))%mod); }
inline long long C(int n,int m) { if (n<m) return 0; return ((fac[n]*1ll*facv[m])*1ll%mod*1ll*facv[n-m])%mod; }
int f[MAXN];
long long g=0;

int main()
{
	scanf("%d%d",&n,&k); INIT();

	for (int i=0;i<=n;i++) f[i]=(int)(C(n,i)*qpow(2,sppow(2,n-i))%mod);//,printf("%lld ",f[i]); puts("end");
	for (int i=k;i<=n;i++) g=(g+optpow(i-k)*(1ll*C(i,k)*f[i]%mod)+mod)%mod;
	printf("%lld\n",g);
}
posted @   Akuto_urusu  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示