20240502比赛总结
[NOIP2017 提高组] 时间复杂度
https://gxyzoj.com/d/hzoj/p/3673
按题意模拟即可
时间复杂度的计算方式是:
-
常数->常数 O(1)
-
常数->n O(n)
-
n->n O(1)
就是细节很多,也不会算时间复杂度,挂成了40
代码:
#include<cstdio>
#include<iostream>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
int T,n,tim,st[105],top,ax[105],ay[105];
string t,name[105];
bool use[30];
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
cin>>t;
tim=0;
if(t!="O(1)")
{
for(int i=4;i<=t.size()-2;i++)
{
tim=tim*10+t[i]-'0';
}
}
int ans=0,cnt=0,fl=0;
for(int i=1;i<=n;i++)
{
ax[i]=ay[i]=0;
string opt;
cin>>opt;
if(opt[0]=='F')
{
string x,y;
cin>>name[i]>>x>>y;
st[++top]=i;
int tmp=name[i][0]-'a';
if(use[tmp])
{
fl=1000;
continue;
}
if(fl) continue;
use[tmp]=1;
int a=0,b=0;
if(x[0]=='n') a=200;
else
{
for(int i=0;i<x.size();i++) a=a*10+x[i]-'0';
}
if(y[0]=='n') b=200;
else
{
for(int i=0;i<y.size();i++) b=b*10+y[i]-'0';
}
if(a>b)
{
fl=i;
continue;
}
if(b>a&&b==200) cnt++;
ans=max(ans,cnt);
ax[i]=a,ay[i]=b;
}
else
{
if(top==0)
{
fl=1000;
continue;
}
int x=st[top];
top--;
int tmp=name[x][0]-'a';
use[tmp]=0;
if(fl==x) fl=0;
if(ax[x]<ay[x]&&ay[x]==200&&!fl) cnt--;
}
// printf("%d %d\n",top,cnt);
}
if(fl==1000) printf("ERR\n");
else if(top) printf("ERR\n");
else if(ans==tim) printf("Yes\n");
else printf("No\n");
for(int i=0;i<=26;i++)
{
use[i]=0;
}
top=0;
}
return 0;
}
T2 [CSP-S2019] Emiya 家今天的饭
https://gxyzoj.com/d/hzoj/p/3674
很明显,每种烹饪方式只会做一道菜
从最基本的考虑,如果只有2种食材,设
推广,记
设
直接枚举x求解即可,时间复杂度
考虑继续优化,可以发现,我们只关心差值而不关心具体的值,所以只用记录x的使用次数与其他食材的使用次数的差即可
时间复杂度
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int p=998244353;
int n,m;
ll a[105][2005],sum[105],dp[205][505];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%lld",&a[i][j]);
sum[i]+=a[i][j];
sum[i]%=p;
}
}
ll ans=1;
for(int i=1;i<=n;i++) ans=ans*(sum[i]+1)%p;
ans=(ans-1+p)%p;
for(int j=1;j<=m;j++)
{
memset(dp,0,sizeof(dp));
dp[1][n+10]=1;
dp[1][n+11]=a[1][j];
dp[1][n+9]=(sum[1]-a[1][j]+p)%p;
for(int i=2;i<=n;i++)
{
for(int k=-n;k<=n;k++)
{
int l=k+n+10;
dp[i][l]=dp[i-1][l]+a[i][j]*dp[i-1][l-1]%p+(sum[i]+p-a[i][j])%p*dp[i-1][l+1]%p;
dp[i][l]%=p;
}
}
for(int k=1;k<=n;k++)
{
int l=k+n+10;
ans=(ans+p-dp[n][l])%p;
}
}
printf("%lld",ans);
return 0;
}
T3 [yLOI2020] 凉凉
https://gxyzoj.com/d/hzoj/p/3668
n<=14,考虑状压
设
显然,转移方程为:
时间复杂度
考虑优化,可以使用一些技巧性的枚举方式:for(int st=s;st;st=((st-1)&s))
时间复杂度O(能过)
代码:
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
int n,m,s1[15];
ll a[15][100005],sum[15][15],dp[15][16400];
bool vis[15][100005],v[15][15];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%lld",&a[i][j]);
}
}
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
for(int j=1;j<=x;j++)
{
int y;
scanf("%d",&y);
for(int k=1;k<=n;k++)
{
sum[i][k]+=a[k][y];
if(vis[k][y])
{
v[i][k]=v[k][i]=1;
}
}
vis[i][y]=1;
}
}
for(int i=1;i<=n;i++)
{
for(int j=n;j>0;j--)
{
s1[i]=s1[i]<<1|v[i][j];
}
}
int tmp=(1<<n)-1;
for(int i=0;i<=n;i++)
{
for(int j=0;j<=tmp;j++)
{
dp[i][j]=1e18;
}
}
dp[0][0]=0;
for(int i=1;i<=n;i++)
{
for(int s=0;s<=tmp;s++)
{
dp[i][s]=dp[i-1][s];
for(int st=s;st;st=((st-1)&s))
{
ll res=0,fl=0;
for(int j=1;j<=n;j++)
{
if(((1<<(j-1))&st)!=0)
{
if(st&s1[j])
{
fl=1;
break;
}
res+=sum[j][i];
}
}
if(!fl) dp[i][s]=min(dp[i][s],res+dp[i-1][s^st]);
// printf("%d %d %d %lld %lld\n",i,s,st,res,dp[i][s|st]);
}
}
}
printf("%lld",dp[n][tmp]);
return 0;
}
T4 [联合省选 2020 A]树
https://gxyzoj.com/d/hzoj/p/1934
用trie树暴力维护,在每个节点合并答案即可
代码:
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
#define N 550005
int n,a[N],edgenum,head[N];
struct edge{
int to,nxt;
}e[N<<1];
void add_edge(int u,int v)
{
e[++edgenum].nxt=head[u];
e[edgenum].to=v;
head[u]=edgenum;
}
struct node{
int cnt,dep,sum,ch[2];
}tr[N*21];
int rt[N],tot;
void pushup(int id)
{
int ls=tr[id].ch[0],rs=tr[id].ch[1];
tr[id].sum=tr[ls].sum^tr[rs].sum^((tr[rs].cnt&1)<<tr[id].dep);
}
void insert(int &id,int u,int d)
{
if(!id)
{
id=++tot;
tr[id].dep=d;
}
tr[id].cnt++;
if(d>20) return;
int tmp=((u>>d)&1);
insert(tr[id].ch[tmp],u,d+1);
pushup(id);
}
int merge(int x,int y)
{
if(!x||!y) return x+y;
tr[x].cnt+=tr[y].cnt;
tr[x].ch[0]=merge(tr[x].ch[0],tr[y].ch[0]);
tr[x].ch[1]=merge(tr[x].ch[1],tr[y].ch[1]);
pushup(x);
return x;
}
void add(int id)
{
if(!id||tr[id].dep>20) return;
add(tr[id].ch[1]);
swap(tr[id].ch[0],tr[id].ch[1]);
pushup(id);
}
int ans[N];
void dfs(int u,int fa)
{
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(v==fa) continue;
dfs(v,u);
rt[u]=merge(rt[u],rt[v]);
}
add(rt[u]);
insert(rt[u],a[u],0);
ans[u]=tr[rt[u]].sum;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=2;i<=n;i++)
{
int fa;
scanf("%d",&fa);
add_edge(i,fa);
add_edge(fa,i);
}
dfs(1,0);
ll res=0;
for(int i=1;i<=n;i++)
{
res+=1ll*ans[i];
// printf("%d ",ans[i]);
}
printf("%lld",res);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效