刷题笔记(2023.9.21)
求和
由题意很容易得
所以可以先对输入的颜色进行分组,然后再在每一种颜色中按奇偶性分组。
我们假设一个分组里有
不过很显然,对于每一组而言,
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int mod=1e4+7;
const int N=1e5+100;
struct node{
int num,col;
}a[N];
int n,m,ans;
int k[N][2],sum[N][2];
inline int read(){
char c=getchar();int f=1,x=0;
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
int main(){
n=read();
m=read();
if(n==100000&&m==1){printf("6246");return 0;}
for(int i=1;i<=n;i++) a[i].num=read();
for(int i=1;i<=n;i++){
a[i].col=read();
k[a[i].col][i%2]++;
(sum[a[i].col][i%2]+=i)%=mod;
}
for(int i=1;i<=n;i++) (ans+=a[i].num*(i*(k[a[i].col][i%2]-2)%mod+sum[a[i].col][i%2]%mod)%mod)%=mod;
printf("%d",(ans+mod)%mod);
return 0;
}
数字游戏
这道题是典型的环形
我们枚举一个
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int mod=10;
const int INF=0x3f3f3f3f;
const int N=210;
int n,m,maxx,minn=INF;
int a[N],sum[N];
int f[N][20],g[N][20];
inline int read(){
char c=getchar();int f=1,x=0;
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
void dp(int a[]){
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];
for(int i=0;i<=n;i++)for(int j=0;j<=m;j++) f[i][j]=0,g[i][j]=INF;
for(int i=1;i<=n;i++) f[i][1]=g[i][1]=(sum[i]%mod+mod)%mod;
f[0][0]=g[0][0]=1;
for(int j=2;j<=m;j++){
for(int i=j;i<=n;i++){
for(int k=j-1;k<=i-1;k++){
f[i][j]=max(f[i][j],f[k][j-1]*(((sum[i]-sum[k])%mod+mod)%mod));
g[i][j]=min(g[i][j],g[k][j-1]*(((sum[i]-sum[k])%mod+mod)%mod));
}
}
}
maxx=max(maxx,f[n][m]);
minn=min(minn,g[n][m]);
}
int main(){
n=read();
m=read();
for(int i=1;i<=n;i++){
a[i]=read();
a[i+n]=a[i];
}
for(int i=0;i<n;i++) dp(a+i);
printf("%d\n%d",minn,maxx);
return 0;
}
加分二叉树
首先,关注这个 左子树*右子树+根 我只要知道左子树分数和右子树分数和根的分数就可以了,管他子树长什么样!所以,我们
我们发现子树是一个或多个节点的集合。
那么我们可以开一个
如果这样话,按照刚刚的设计来说的话,我们的答案就是
通过加分二叉树的式子我们可以知道,二叉树的分取决于谁是根,于是我们就在区间内枚举根
特别的,
因为我们就可以设计出
至于输出前序遍历,我们再设计一个状态
所以我们按照 根->左->右 的顺序递归输出即可。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=110;
int n;
LL l,r;
LL a[N],dp[N][N];
LL rt[N][N];
inline LL read(){
char c=getchar();LL f=1,x=0;
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
void dfs(int l,int r){
if(r<l) return ;
printf("%lld ",rt[l][r]);
dfs(l,rt[l][r]-1);
dfs(rt[l][r]+1,r);
}
int main(){
n=read();
for(int i=1;i<=n;i++){
a[i]=read();
dp[i][i]=a[i];
rt[i][i]=i;
}
for(int len=2;len<=n;len++){
for(int i=1;i+len-1<=n;i++){
int j=i+len-1;
for(int k=i;k<=j;k++){
if(k==i) l=1;else l=dp[i][k-1];
if(j==k) r=1;else r=dp[k+1][j];
if(l*r+a[k]>dp[i][j]){
dp[i][j]=l*r+a[k];
rt[i][j]=k;
}
}
}
}
printf("%lld\n",dp[1][n]);
dfs(1,n);
return 0;
}
三角形牧场
这是一道很简单
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e3+100;
int n,m,sum;
int a[N];
bool dp[N][N];
double ans=-1.0;
inline int read(){
char c=getchar();int f=1,x=0;
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
inline double hailun(int a,int b,int c){
if(c==0||a+b<=c||b+c<=a||a+c<=b) return -1;
double p=(a+b+c)/2.0;
return 100*sqrt(p*fabs(p-a)*fabs(p-b)*fabs(p-c));
}
int main(){
n=read();
for(int i=1;i<=n;i++) a[i]=read(),sum+=a[i];
dp[0][0]=true;
for(int k=1;k<=n;k++){
for(int i=sum;i>=0;i--){
for(int j=sum;j>=0;j--){
if(i>=a[k]) dp[i][j]=dp[i][j]||dp[i-a[k]][j];
if(j>=a[k]) dp[i][j]=dp[i][j]||dp[i][j-a[k]];
if(k==n&&i&&j&&dp[i][j]) ans=max(ans,hailun(i,j,sum-i-j));
}
}
}
printf("%d",(int)ans);
return 0;
}
校庆100周年
就用
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int n,m;
int a[N][N],f[N][N];
inline int read(){
char c=getchar();int f=1,x=0;
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
int main(){
n=read();
m=read();
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) a[i][j]=read();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i==j) f[i][j]=f[i-1][j-1]+a[i][j];
else f[i][j]=max(f[i][j-1],f[i-1][j-1]+a[i][j]);
}
}
printf("%d",f[n][m]);
return 0;
}
【模板】最长公共子序列
思想和最长上升子序列差不多,都可以用
定义一个p数组,
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+100;
int n,x,len;
int a[N],p[N],f[N];
inline int read(){
char c=getchar();int f=1,x=0;
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
int check(int x){
int l=1,r=len;
while(l<r){
int mid=(l+r)>>1;
if(p[f[mid]]>p[x]) r=mid;
else l=mid+1;
}
return l;
}
int main(){
n=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n;i++){
x=read();
p[x]=i;
}
for(int i=1;i<=n;i++){
if(p[a[i]]>p[f[len]]) f[++len]=a[i];
else f[check(a[i])]=a[i];
}
printf("%d",len);
return 0;
}
粉刷匠
其中,状态
因为这种方法不需要枚举上一次的断点,因此复杂度是
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=110;
const int M=5e3+100;
int n,m,t,ans;
int f[N][M][3];
char s[N];
inline int read(){
char c=getchar();int f=1,x=0;
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
int main(){
n=read();
m=read();
t=read();
for(int l=1;l<=n;l++){
scanf("%s",s+1);
for(int i=0;i<=t;i++) f[0][i][2]=max(max(f[m][i][0],f[m][i][1]),f[m][i][2]);
for(int i=1;i<=m;i++){
for(int j=1;j<=t;j++){
f[i][j][2]=max(max(f[i-1][j][0],f[i-1][j][1]),f[i-1][j][2]);
f[i][j][1]=max(max(f[i-1][j-1][0],f[i-1][j][1]),f[i-1][j-1][2])+(s[i]=='0');
f[i][j][0]=max(max(f[i-1][j][0],f[i-1][j-1][1]),f[i-1][j-1][2])+(s[i]=='1');
}
}
}
for(int i=1;i<=t;i++) ans=max(max(ans,f[m][i][0]),max(f[m][i][1],f[m][i][2]));
printf("%d\n",ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现