1
lucas定理
p进制,每一位
必须大于等于
f[i]表示以a[i]结尾的序列的个数。
枚举j 若
,则
直接枚举 的子集
发现加的复杂度高,赋值的复杂度低,考虑平衡一下。
枚举子集:
超集:
分成两部分,f[i][j]表示右边9位是j,左边9位是i集合超集的
的和。
现在更新要更新
,求和需要
.
2
小星星
一一对应,使得树上有边图上也有边
在树上做
表示i对应图中j,i的子树有多少种标号方法
表示原图中i,j是否联通
for(int i=head[u];i;i=ed[i].next)
{
int v=ed[i].to;
if(v==fa) continue;
dfs(v,u);
for(int j=0;j<n;j++)
{
long long s=0;
for(int k=0;k<n;k++)
{
if(g[j][k]) s+=f[v][k];
}
f[u][j]*=s;
}
}
这个dp我们强制允许图上的一个点对应树上的多个点(不允许没法做…)
然后进行一波容斥。
枚举一个子集,然后只用这个集合里的点做一次dp
然后根据这个集合与全集的大小之差判断符号。
如果差了奇数,减去,否则加上
这样除了全集以外每个集合正负恰好抵消。
比如:1100
在1111时被计算一次
在计算1101 1110时减去两次
在计算1100的时候被加上一次
最后不被统计进答案里。
原来n=17是给容斥的…
3
按位或
min-max容斥
比较好求期望
设第i位成为1的时间是
min比较好处理,要么染到,要么没染到。
考虑没有染到的概率。
染到的概率是
,那么期望时间是
染到的概率不好求,转化为求没染到的概率。
对于每个集合,求所有子集的概率和
输入
对于每个j,求所有满足
的
之和,设为
处理前缀和:
for(int j=0;j<n;j++)
{
for(int i=0;i<(1<<n);i++)
{
if((i>>j)&1) s[i]+=s[i^(1<<j)]
}
}
4
分治
void work(int l,int r)
{
if(l==r) return;
int mid=(l+r)>>1;
work(l,mid);
solve() //处理左边对右边的影响
work(mid+1,r);
}