12 月 cls 记录
2021.12.13:
南京大屠杀纪念日,默哀。
十年前的题我也是望尘莫及,哈哈!这是一个神奇的 DP 题。
考虑它的条件:在 n 的所有子集中挑出 m 个,
-
任意集合非空;
-
任意集合最多出现一次;
-
任意数字出现次数为偶数次。
设 fi 为挑出了 i 个集合满足条件的方案数。
这样的状态看似不合理,没有办法毫无联系,难以转移,却可以通过容斥转移。
考虑只要确定了前面的,由第三条就可以确定最后一个,故此时方案为 Pi−12n−1
考虑第一条,即前面的集合不能恰好满足每一个都是偶数,所以减去 fi−1
考虑第二条,假设前面有一个 j 使得集合 i,j 相等,那么此时剩下的 i−2 个集合是满足条件的,而 j 有 i−1 种选法,集合 i,j 有 2n−1−(i−2) 种选法,故减去 (i−2)(2n−i+1)fi−2
综上,fi=Pi−12n−1−fi−1−(i−2)(2n−i+1)fi−2
注意,我们一直是按有序算的,故最后还要除以 m!
#include<bits/stdc++.h>
using namespace std;
#define inf 1e9
const int maxn=1e6+10;
const int mod=1e8+7;
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
inline int ksm(int x,int y){
int res=1;
while(y){
if(y&1)res=1ll*res*x%mod;
x=1ll*x*x%mod;y>>=1;
}return res;
}
int n,m,f[maxn],fac=1;
int main(){
n=read(),m=read();
int pw=ksm(2,n),cur=pw-1;
f[0]=1,f[1]=0;
for(int i=2;i<=m;i++){
f[i]=((cur-f[i-1]-1ll*(i-1)*(pw-i+1)%mod*f[i-2]%mod)%mod+mod)%mod;
cur=1ll*cur*(pw-i)%mod;fac=1ll*fac*i%mod;
}printf("%d\n",1ll*f[m]*ksm(fac,mod-2)%mod);
return 0;
}
深深地感到自己的弱小。
2021.12.21:
考的 pnershy 的题,不想改。第一题是三维偏序,别人都用的二维树状数组,只有我傻乎乎地用 cdq,第二题是 bitset 优化二进制分组背包,而我只会傻乎乎地分治 ntt。学到了,判断和为 n 的一堆数能否组成 k 的最优复杂度不是 nlog2n 而是 n√nlogn/w
补了昨天 demonlover 的题。其中的 cf1120d 比较有意思。每个节点相当于操作一个区间,也相当于操作差分数组的两个点,所以想到最小生成树。判断每条边有无可能在最小生成树上,就是对于每一个权值,之前的随意取一棵最小的,然后判断当前可不可以加入。是个有意思的小 trick
#include<bits/stdc++.h>
using namespace std;
#define inf 1e9
const int maxn=2e5+10;
const int mod=1e9+7;
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
#define ll long long
int n,m,w[maxn],tot,ok[maxn];ll ans;
int beg[maxn],nex[maxn<<1],to[maxn<<1],e;
inline void add(int x,int y){
e++;nex[e]=beg[x];beg[x]=e;to[e]=y;
e++;nex[e]=beg[y];beg[y]=e;to[e]=x;
}
int l[maxn],r[maxn],ti,f[maxn];
struct node{int x,y,z,id;}E[maxn];
inline void dfs(int x,int fa){
int flag=0;l[x]=ti+1;
for(int i=beg[x];i;i=nex[i]){
int t=to[i];
if(t==fa)continue;
dfs(t,x);flag=1;
}if(!flag)++ti;r[x]=ti;
E[x]=(node){l[x],r[x]+1,w[x],x};
//printf("%d [%d,%d]\n",x,l[x],r[x]);
}
inline int cmp(node x,node y){return x.z<y.z;}
inline int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
int main(){
freopen("crops.in","r",stdin);
freopen("crops.out","w",stdout);
n=read();
for(int i=1;i<=n;i++)
w[i]=read();
for(int i=1,x,y;i<n;i++)
x=read(),y=read(),add(x,y);
dfs(1,0);sort(E+1,E+1+n,cmp);
for(int i=1;i<=n;i++)f[i]=i;
for(int i=1,j=1;i<=n;i=j){
for(j=i+1;j<=n&&E[i].z==E[j].z;j++);
for(int k=i;k<j;k++)
if(find(E[k].x)!=find(E[k].y))
tot++,ok[E[k].id]=1;
for(int k=i;k<j;k++)
if(find(E[k].x)!=find(E[k].y))
ans+=E[k].z,f[find(E[k].x)]=find(E[k].y);
}printf("%lld %d\n",ans,tot);
for(int i=1;i<=n;i++)
if(ok[i])printf("%d ",i);puts("");
return 0;
}
补了一下之前 vp 的 Educational Round 94,里面的 F 和 G 比较有意思。
有时候真的是奇奇怪怪的题目做多了,反而想不到最简单、最本真、最自然的想法。
看到 m≤20,我还在想什么呢,容斥啊!Ans=∑T⊆S(−1)|T|+1f(T),其中 f(T) 表示硬选这些边的方案数。
剩下的部分就是容易的了,还有就是要预处理一个前缀和。
补了之前考时没做出来的题,喜提一场绿。CF1617E Christmas Chocolates
抽象成一个图论问题。无向图,无穷个点,若 x+y=2k 则有边,求 n 个特殊点中两两最短路的最大值。
因为是无向图,我们考虑大的往小的连边。我们惊喜地发现这样的边只有一条,即 2k 恰好大于 x 时有解。易证。
于是原图退化成了一棵 nlogn 级别个点的树。求两叶子节点间的最大距离即可。随意实现。我的 bfs 实现比较诡异。
#include<bits/stdc++.h>
using namespace std;
#define inf 1e9
const int maxn=2e5+10;
const int mod=1e9+7;
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
#define fi first
#define se second
#define pii pair<int,int>
#define mkp make_pair
map<int,pii>mp;
inline int f(int x){for(int i=0;;i++)if((1<<i)>=x)return (1<<i);}
int n,m,k,s,u,v,ans;
int main(){
n=read();
for(int i=1,x;i<=n;i++)
x=read(),mp[x]=mkp(0,i);
while(k=(--mp.end())->fi){
s=f(k)-k;
if(mp.find(s)!=mp.end()&&ans<mp[s].fi+mp[k].fi+1){
ans=mp[s].fi+mp[k].fi+1;u=mp[s].se,v=mp[k].se;
}if(mp[s].fi<mp[k].fi+1)mp[s]=mkp(mp[k].fi+1,mp[k].se);
mp.erase(k);
}printf("%d %d %d\n",u,v,ans);
return 0;
}
复习了 AC 自动机。做了 P3121 [USACO15FEB]Censoring G
2021.12.22:
上午考 codycode 的比赛,T3 简单题,注意 dp 函数的单调性即可。
写 AC 机题意外收获一个树上 trick,给一堆节点到跟的路径加 1:按 dfs 序排序,pi+1,lca(pi,pi+1)−1
和 verdandi 联手 vp 了 The 2021 China Collegiate Programming Contest (Harbin),题解
补了一下昨天的鸽掉的 cf1400f,感觉最近碰到的 AC 自动机题好多,晕。
大概就是字符串和数论的结合是不好做的,考虑到 X 极小,不妨生成所有的 X−prime 串。这时题意变为最少删除几个使不包含任一生成串。对生成串建 AC 自动机,设 dpi,j 表示考虑到第 i 位,此时在自动机上走到节点 j 所需的最小删除个数。两种情况,若下一个删除则有 dpi,j+1→dpi+1,j,否则若下一个节点不是 endpos 则有 dpi,j→dpi+1,ch[j][s[i]−′0′] ,数组滚一下。
#include<bits/stdc++.h>
using namespace std;
const int inf=1e9;
const int maxn=1e6+10;
const int mod=1e9+7;
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
int n,m,k,dp[2][maxn];
int ch[maxn][10],cnt,fa[maxn],edp[maxn];
inline void insert(string ss){
int u=0;
for(int i=0;i<ss.size();i++){
int t=ss[i]-'0';
if(!ch[u][t])ch[u][t]=++cnt;
u=ch[u][t];
}edp[u]=1;
}
inline void chk(string ss){
for(int i=0;i<ss.size();i++){
int S=0;
for(int j=i;j<ss.size();j++){
S+=ss[j]-'0';
if(k>S&&k%S==0)return;
}
}insert(ss);
}
inline void gen(string ss,int S){
if(S>k)return;
if(S==k)return void(chk(ss));
for(int i=1;i<=9;i++)
gen(ss+(char)(i+'0'),S+i);
}
queue<int>q;
inline void build(){
for(int i=0;i<=9;i++)
if(ch[0][i])q.push(ch[0][i]);
while(!q.empty()){
int x=q.front();q.pop();
for(int i=0;i<=9;i++){
int &v=ch[x][i];
if(v)fa[v]=ch[fa[x]][i],q.push(v);
else v=ch[fa[x]][i];
}
}
}
string s;
inline void chkmin(int &x,int y){x=(x<y?x:y);}
int main(){
cin>>s;n=s.size();
k=read();gen("",0);//puts("over");
build();
memset(dp,0x3f,sizeof(dp));
dp[0][0]=0;
for(int i=1;i<=n;i++){
for(int j=0;j<=cnt;j++)dp[i&1][j]=inf;
for(int j=0;j<=cnt;j++){
chkmin(dp[i&1][j],dp[~i&1][j]+1);
if(!edp[ch[j][s[i-1]-'0']])
chkmin(dp[i&1][ch[j][s[i-1]-'0']],dp[~i&1][j]);
}
}int ans=inf;
for(int i=0;i<=cnt;i++)
chkmin(ans,dp[n&1][i]);
printf("%d\n",ans);
return 0;
}
2021.12.23:
做了一道 usaco 的题 [USACO21FEB] No Time to Dry P
尽量多涂,对于相邻的两个相同的,若其中间没有比它们小的就可以减少一次,预处理出这样的区间,容斥一手即可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· 用 DeepSeek 给对象做个网站,她一定感动坏了
· DeepSeek+PageAssist实现本地大模型联网
· 手把手教你更优雅的享受 DeepSeek
· Java轻量级代码工程
· 从 14 秒到 1 秒:MySQL DDL 性能优化实战