首页 > 其他分享 >20240807学习

20240807学习

时间:2024-08-08 15:40:52浏览次数:8  
标签:int void long 学习 20240807 inline mul mod

这回讲了点简单的动态规划,终于写的出来blog了

gym105239I Path And k Vertices

题面:有一个\(n\)个点的树,每个点有点权\(a_i\),可以在任意叶子节点到根节点的路径中选\(k\)个点,求点权和的最大值。
题解:DFS的时候使用数据结构分别维护该节点到根的最大的\(k\)个点和该节点到根的剩下点,本人使用std::set
复杂度\(\text O(n(\log k+\log n))\)
话说这真的是DP吗
代码:

#include<cstdio>
#include<set>
#define int long long
const int N=300005;
int n,head[N],pedge,root,now,ans,w[N],od[N],k;
std::set<int>s1,s2;
struct Edge{
    int to,next;
}edge[N];
inline void ins(int u,int v){edge[++pedge]={v,head[u]},head[u]=pedge;}
inline void Max(int&x,int y){x<y&&(x=y);}
inline bool cmp(int x,int y){return x>y;}
void dfs(int u){
    now+=w[u],s1.insert(w[u]);
    if(s1.size()>k)now-=*s1.begin(),s2.insert(*s1.begin()),s1.erase(*s1.begin());
    if(!od[u])Max(ans,now);
    for(int e=head[u];e;e=edge[e].next)dfs(edge[e].to);
    if(s1.find(w[u])!=s1.end()){
        now-=w[u],s1.erase(w[u]);
        if(s1.size()<k&&s2.size())now+=*s2.rbegin(),s1.insert(*s2.rbegin()),s2.erase(*s2.rbegin());
    }
    else s2.erase(w[u]);
}
signed main(){
    scanf("%lld%lld",&n,&k);
    for(int i=1,u,t;i<=n;i++){
        scanf("%lld%lld",&u,&t),w[i]=t;
        if(u)ins(u,i),od[u]++;
        else root=i;
    }
    dfs(root),printf("%lld\n",ans);
    return 0;
}

gym105239C Colored Tree

题面:有\(n\)个点,点有点权\(w_i\)和颜色\(c_i\),定义好的集合满足:点集中的点不能相邻,点集中的颜色互不相同。求好的集合的点权和最大值。
题解:定义\(f(u,S,t)\),表示节点\(u\)的状态为\(t\)(\(t=0\)表示不选择\(u\),\(t=1\)表示选择\(u\)),且\(u\)的子树的选取的集合构成的颜色集合。
每次让\(u\)的字节点\(v\)更新\(u\)的答案有转移方程
\(f(u,S,1)=\max_{T\sube S}(f(v,T,0)+f(u,S\setminus T,1))\)
\(f(u,S,0)=\max_{T\sube S}(\max(f(v,T,0),f(v,T,1))+f(u,S\setminus T,1))\)
复杂度\(\text O(n3^{|C|})\)
代码:

#include<cstdio>
#define int long long
const int N=1005,A=1<<10,M=A+5;
int n,w[N],c[N],head[N],pedge,f[N][M][2],C,ans;
struct Edge{
    int to,next;
}edge[N<<1];
inline void Ins(int u,int v){edge[++pedge]={v,head[u]},head[u]=pedge;}
inline void ins(int u,int v){Ins(u,v),Ins(v,u);}
inline void Max(int&x,int y){x<y&&(x=y);}
inline int max(int x,int y){return x>y?x:y;}
void dfs(int u,int father){
    f[u][1<<c[u]][1]=w[u];
    for(int e=head[u];e;e=edge[e].next){
        int v=edge[e].to;
        if(v^father){
            dfs(v,u);
            for(int s=(1<<C)-1;s;s--)for(int t=s;t;t=(t-1)&s)Max(f[u][s][0],max(f[v][t][0],f[v][t][1])+f[u][s^t][0]),Max(f[u][s][1],f[v][t][0]+f[u][s^t][1]);
        }
    }
}
signed main(){
    scanf("%lld%lld",&n,&C);
    for(int i=1;i<=n;i++)scanf("%lld",w+i);
    for(int i=1;i<=n;i++)scanf("%lld",c+i),c[i]--;
    for(int i=1,u,v;i<n;i++)scanf("%lld%lld",&u,&v),ins(u,v);
    dfs(1,0);
    for(int i=0;i<1<<C;i++)Max(ans,max(f[1][i][0],f[1][i][1]));
    return printf("%lld\n",ans),0;
}

gym105244G Evolutionary Tree Weights

题面:有\(G\)个由AGCT组成长度为\(m\)的字符串,\(T\)个询问,每次询问给出一棵树和树的叶节点分别对应哪些字符串,定义边权为两条边所对应的字符串不同的位置的个数。你可以在除了叶子节点的每一个点填上一个由AGCT组成长度为\(m\)的字符串,求字符串树的边权和的最小值。
题解:发现每一位对答案的影响独立,分别讨论每一位,令\(f(u,c)\)表示节点\(u\)填\(c\)后子树的边权和,那么对\(u\)的子节点\(v\),\(f(u,c)=\sum_{v\in son(u)}\max_{k=0}^3(f(v,k)+[k\neq c])\)
代码:

#include<cstdio>
#include<cstring>
#define int long long
const int N=505,INF=0x3f3f3f3f;
char s[N][N];
int g,k,T,n,m,head[N],pedge,a[N],b[N],f[N][4],ans;
bool od[N];
struct Edge{
    int to,next;
}edge[N];
inline void ins(int u,int v){edge[++pedge]={v,head[u]},head[u]=pedge;}
inline void Min(int&x,int y){y<x&&(x=y);}
inline int min(int x,int y){return x<y?x:y;}
inline int min(int x,int y,int z,int w){return min(min(x,y),min(z,w));}
inline int trans(char c){
    return c=='A'?0:c=='G'?1:c=='C'?2:3;
}
void dfs(int u){
    if(od[u])return;
    f[u][0]=f[u][1]=f[u][2]=f[u][3]=0;
    for(int e=head[u];e;e=edge[e].next){
        int v=edge[e].to;
        dfs(v);
        for(int c=0;c<4;c++){
            int minn=INF;
            for(int k=0;k<4;k++)Min(minn,f[v][k]+(k!=c));
            f[u][c]+=minn;
        }
    }
}
signed main(){
    scanf("%lld",&g);
    for(int i=1;i<=g;i++)scanf("%s",s[i]+1);
    for(k=strlen(s[1]+1),scanf("%lld",&T);T--;){
        scanf("%lld%lld",&n,&m);
        if(n==0){
            puts("0");
            continue;
        }
        pedge=ans=0;
        for(int i=1;i<=n;i++)head[i]=od[i]=0;
        for(int i=2,p;i<=n;i++)scanf("%lld",&p),ins(p,i);
        for(int i=1;i<=m;i++)scanf("%lld%lld",a+i,b+i),od[a[i]]=1;
        for(int i=1;i<=k;i++){
            for(int j=1;j<=m;j++)f[a[j]][0]=f[a[j]][1]=f[a[j]][2]=f[a[j]][3]=INF,f[a[j]][trans(s[b
            [j]][i])]=0;
            dfs(1),ans+=min(f[1][0],f[1][1],f[1][2],f[1][3]);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

gym105173I Password

题面:一个长度为\(n\)的序列\(a\),每一项都是\(1\)到\(k\)的整数,对于每一个长度为\(k\)的子区间,如果内容为\(1\)到\(k\)的排列,那么是好的子区间。问有多少种序列满足每个数至少被包含在一个子区间中。
题解:
令\(f(i)\)表示长度为\(i\)的满足所有位置被至少一个好的子区间包含的方案数。\(g(i)\)表示在一个\(1\)到\(k\)的排列插入\(i\)个数后最后\(k\)个数仍然是一个\(1\)到\(k\)的排列,且插入\(i-1\)个数后不是一个\(1\)到\(k\)的排列的方案数。

\[f(i)=\sum_{j=1}^kf(i-j)g(j) \]

\[g(i)=i!-\sum_{j=1}^{i-1}(j!g(i-j)) \]

时间复杂度\(\text O(nk)\)
代码:

#include<cstdio>
#define int long long
const int N=100005,mod=998244353;
int n,k,fac[N],f[N],g[N];
inline int mul(int x,int y){return x*y%mod;}
inline void Sub(int&x,int y){if((x-=y)<0)x+=mod;}
inline void Add(int&x,int y){if((x+=y)>=mod)x-=mod;}
signed main(){
    scanf("%lld%lld",&n,&k),fac[0]=1;
    for(int i=1;i<=k;i++)fac[i]=mul(fac[i-1],i);
    for(int i=1;i<=k;i++){
        g[i]=fac[i];
        for(int j=1;j<i;j++)Sub(g[i],mul(fac[j],g[i-j]));
    }
    f[k]=fac[k];
    for(int i=k;i<=n;i++)for(int j=1;j<=k&&i+j<=n;j++)Add(f[i+j],mul(f[i],g[j]));
    printf("%lld\n",f[n]);
    return 0;
}

gym105139K Points on the Number Axis B

题面:有\(n\)个数,每次等概率的选择一对相邻的数对\((x_i,x_{i+1})\),替换成\((x_i+x_{i+1})/2\),求最后的数的期望。
题解:现将求期望转化成求所有方案的总和除以总方案数\((n-1)!\),令第\(i\)个数对方案总和的贡献为\(a_i\times f(i-1,n-i)\),其中\(f(i,j)\)表示一个数左边有\(i\)个右边有\(j\)个数后对所有方案总和的贡献。

\[f(i,j)=\left(i-\frac12\right)f(i-1,j)+\left(j-\frac12\right)f(i,j-1) \]

类似与网格图路径计数可以得出:

\[f(i,j)={i+j\choose i}\prod_{k=1}^i\left(k-\frac12\right)\prod_{k=1}^j\left(k-\frac12\right) \]

预处理后复杂度\(\text O(n+\log p)\)
代码:

#include<cstdio>
#define int long long 
const int N=1000005,mod=998244353,inv2=(mod+1)/2;
int n,fac[N],pro[N],finv[N],a[N],ans;
inline int mul(int x,int y){return x*y%mod;}
inline int mul(int x,int y,int z){return mul(mul(x,y),z);}
inline int mul(int x,int y,int z,int w){return mul(mul(x,y),mul(z,w));}
inline void Mul(int&x,int y){x=mul(x,y);}
inline void Add(int&x,int y){if((x+=y)>=mod)x-=mod;}
inline void Sub(int&x,int y){if((x-=y)<0)x+=mod;}
inline int sub(int x,int y){return Sub(x,y),x;}
inline int pow(int x,int y){
    int ret=1;
    for(;y;Mul(x,x),y>>=1)if(y&1)Mul(ret,x);
    return ret;
}
inline int inv(int x){return pow(x,mod-2);}
inline int C(int x,int y){return mul(fac[x],finv[y],finv[x-y]);}
signed main(){
    scanf("%lld",&n),fac[0]=pro[0]=1;
    for(int i=1;i<=n;i++)scanf("%lld",a+i),fac[i]=mul(fac[i-1],i),pro[i]=mul(pro[i-1],sub(i,inv2));
    finv[n]=inv(fac[n]);
    for(int i=n;i;i--)finv[i-1]=mul(finv[i],i);
    for(int i=1;i<=n;i++)Add(ans,mul(a[i],pro[i-1],pro[n-i],C(n-1,i-1)));
    return printf("%lld\n",mul(ans,finv[n-1])),0;
}

标签:int,void,long,学习,20240807,inline,mul,mod
From: https://www.cnblogs.com/junjunccc/p/18349052

相关文章

  • 基于深度学习网络的人员行为视频检测系统matlab仿真,带GUI界面
    1.算法仿真效果matlab2022a仿真结果如下(完整代码运行后无水印):  2.算法涉及理论知识概要       基于GoogLeNet深度学习网络的人员行为视频检测系统是一个高度复杂的计算机视觉应用,它利用深度神经网络的强大功能来识别和分类视频中的人员行为。GoogLeNet,也称为......
  • 【深度学习与NLP】——快速入门Pytorch基本语法
    目录Pytorch基本语法1.1认识Pytorch1.1.1什么是Pytorch1.1.2Pytorch的基本元素操作1.1.3 Pytorch的基本运算操作1.1.4 关于TorchTensor和Numpyarray之间的相互转换1.1.5小节总结1.2Pytorch中的autograd1.2.1关于torch.Tensor1.2.2关于Tensor的操作1.2.3......
  • (leetcode学习)50. Pow(x, n)
    实现 pow(x,n) ,即计算x的整数 n次幂函数(即,xn)。示例1:输入:x=2.00000,n=10输出:1024.00000示例2:输入:x=2.10000,n=3输出:9.26100示例3:输入:x=2.00000,n=-2输出:0.25000解释:2-2=1/22=1/4=0.25提示:-100.0<x<100.0-231<=n<=231......
  • 学习笔记 整体二分
    整体二分是一种离线算法记[l,r]为答案的值域,[L,R]为答案的定义域。(也就是说求答案时仅考虑下标在区间[L,R]内的操作和询问,这其中询问的答案在[l,r]内)我们首先把所有操作按时间顺序存入数组中,然后开始分治。在每一层分治中,利用数据结构(常见的是树状数组)统计当前查询的......
  • AI入门之深度学习:基本概念篇
    1、什么是深度学习1.1、机器学习  图1:计算机有效工作的常用方法:程序员编写规则(程序),计算机遵循这些规则将输入数据转换为适当的答案。这一方法被称为符号主义人工智能,适合用来解决定义明确的逻辑问题,比如早期的PC小游戏:五子棋等,但是像图像分类、语音识别或自然语言翻译等......
  • IT领域新旅程:为高考新生打造的暑期学习路线图
    IT专业入门,高考假期预习指南七月来临,各省高考分数已揭榜完成。而高考的完结并不意味着学习的结束,而是新旅程的开始。对于有志于踏入IT领域的高考少年们,这个假期是开启探索IT世界的绝佳时机。作为该领域的前行者和经验前辈,你是否愿意为准新生们提供一份全面的学习路线图呢?快......
  • 工作日志(记录自己的日常学习和腹诽)
    工作日志为了纪念自己的学习经历,也为了记录自己的试错过程创建于2024.6.11作者:刘佳琪[email protected]安装Keil5,破解软件需要防止被电脑病毒查杀功能删掉。24.06.18proteus8.13版本,51单片机串口无效,需替换MCS8051_7.DLL文件到MCS8051.DLL文件并改名为......
  • vb学习
    在VisualBasic(VB),数据类型用于定义变量可以存储的数据种类。以下是一些常用的VB数据类型:数值类型:Byte:无符号8位整数(0到255)。Integer:有符号16位整数(-32,768到32,767)。UInteger:无符号16位整数。Long:有符号32位整数(-2,147,483,648到2,147,483,647)。ULong:无符号32位整......
  • [rCore学习笔记 023]任务切换
    导读还是要先看官方手册.学过DMA的同志可能比较好理解,一句话,释放CPU总线:如果把应用程序执行的整个过程进行进一步分析,可以看到,当程序访问I/O外设或睡眠时,其实是不需要占用处理器的,于是我们可以把应用程序在不同时间段的执行过程分为两类,占用处理器执行有效任务的计算阶......
  • MySQL基础学习1
    标签(空格分隔):MySQLmysql常见的命令语句查看所有的数据库showdatabases;查看数据库:selectdatabase();打开指定的库use库名;查看当前库的所有表showtables;查看其他库的所有表showtablesform库名;创建表createtable表名(列名列类型,......