省选不杂题乱写(1)
「SDOI2017」相关分析(线段树)
给定序列,,有三种操作:
1. 给定求下式
2.(两个序列分别)区间加(不同值)
3.(两个序列分别)区间修改为(S/T)+i(下标)
sol
分别标记各个部分。
区间加的部分
区间修改的部分
明智的办法,我们先将区间修改为下标,再加上或。
我们得知道
由此来快速算出
「HAOI2012」高速公路(线段树)
所求即为
分别维护区间,,即可。
「SHOI2014」概率充电器(树形DP,up and down,概率)
由于每个节点的价值都是,实际上就是求通电概率和。
是个树形,运用传说中的思想。与换根类似,这也是一种能够处理树上节点信息需要从与其连接各节点(也即包括了子节点与父节点)转移过来
这样问题的方法。
明确一个结论:
两个相独立事件,发生的概率分别为
或者可以说是
接下来针对节点通电考虑这些相独立的事件:
-
自己通电
-
的某儿子(通过的子树)通电,并且连向该儿子的边通电
-
的父亲(通过了子树之外的节点)通电,并且与父亲相连的边通电
根据那啥思想,可以尝试第一遍先处理跟,得到只考虑这两种情况下的答案,第二遍再处理。
首先是,根据上面那个独立事件和概率,更新时,对于节点以及其子节点:
然后是。对于一组和,真正的是已经求出的,然后要获得在不计算时的答案,设这个答案为。则:
需要注意的是,这里分母可能是。这种情况下由于已经是,不需要继续更新。
最后
「SDOI2010」地精部落(DP,排列)
什么妖魔鬼怪题解区,晕了....
求波动排列数。
排列的可用性质?
由于这里只涉及大小比较,我们可以只考虑一个。
也就是说的排列和的排列是一样的捏()
并且往后排列只关心相邻两数的大小关系。于是我们可以设状态:
表示的排列,最后一个数为并且为山谷/峰的波动排列数。则:
复杂度,前缀和和滚动数组优化后。
浅言一下求排列的题目特征()我自己喜欢把部分离散为相对大小,而常见的做法是加入一个新的最大数,然后考虑这个数和前面每个数交换产生的结果。
[LNOI2014] LCA(LCA,离线)
以前写过为什么现在又忘了啊()
而且也没有做法离线的敏感度了。这里大概是从查询形式是到来看出,要么是数据结构要么是离线前缀和作差(?
(
具体是这样的,更进一步地,
查询一堆点-一个点的深度和,就可以变成这样一个算法:
将这堆点每个点到根节点的路径每个点权值都,再计算这个单点到根节点的权值和。
既然是路径修改就可以树剖辽!
但是我们每次做查询的时候肯定是将某个区间的点按照上述前半句的方式加进来,再对另外某个单点进行这样权值和的查询。
把询问,离线下来,依次修改每个点到根的路径,到点查询记录答案,做完了()
Luogu P3413 SAC#1 - 萌数(数位DP,单步容斥)(没写)
正着不好做就反着做,我连这个都忘了吗...
这个东西叫单步容斥:
使用单步容斥的可循标志是:一般计算不含xx的方案数更好做一点。
既然是至少长度为的回文串,我们其实只需要考虑长度为或的。
要求不带回文串的数,我们只需要不存在以及的情况即可。转移时由于只需要考虑前两个位置,我们设表示有位,最后一位为,倒数第二位为的无回文串数。
感觉能加矩阵..?
哦,等一下,要求的是到的啊..
[HNOI2015]落忆枫音(DAG,DP,计数)
首先考虑这个的答案。给每个节点都选一个父亲,由乘法原理:
然后考虑加一条边成环
加边,那么这条边会与一条的路径形成一个环。当我们选择了某整个环,就会形成一个不合法方案。
我超,想了一个上午没想明白的原来是这个事情。构造一棵外向树,我只可能选择一条的路径。
那么每个这样一条包含个点的路径造成的不合法方案数是:
这可不兴算啊(
可以把这种:
当我们在一条的路径上由走一步,那么经过了的这条路径到达了之后,这所有的路径在这里就固定了选边,于是方案数会。设表示所有路径固定时的不合法构造方案数,拓扑上,那么有:
其中初始化。最后:
记得
2014 湖北省队互测 week2 已经没有什么好害怕的了(DP,二项式反演)
另外一种能(PS:这题实际上并非多步容斥,而是二项式反演。形式上与多步容斥有些类似,但并非“恰好”与“至少”,而是“恰好”与“钦定”的转变。
放个引用的题目:【TopCoder10697】RabbitNumbering
构造个整数,每个数可选的区间为,求序列构造方案数。
跟顺序没关系的话很容易想。这样一来,选择第个数的时候,前个数无论怎么选,都在这个区间内。于是就有。
感觉理解不够,再放一道UVA1485 Permutation Counting
这玩意不大一样,这个都是排列()
用我们之前遇到排列题目的做法,然后得到以下解法:
设表示个数,值为的方案数。
加入第个数,如果和前面一个有的换,,那还是(
如果和前面一个没E的换,那就了。得:
好的,回到这个题目,我们同样先排个序
易得要求组两两匹配方案数。
此题与兔数做法相似的点在于,如果匹配出了对,要匹配一个小于其的的方式就会减少。
难做的点在于,如果匹配了一组,那么我们很难得知,与的大小关系。
那么我们就先匹配!
设表示前个糖果钦定了组的方案数,表示小于的个数,那么:
这是先钦定个。再有钦定个,其余任选的有重方案数:
最后是表示恰好组的,满足:
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 集合计数(二项式反演)
同样是二项式反演的题。我先钦定交集中包含了个元素,则:
表示恰好交集大小为的集合选择方案数,则:
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);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具