2022.10.7模拟赛
T1
题面#
思路#
考试的时候并没有想到用什么高级的方法算这个玩意er,所以就直接先算 A
然而正解就是先算BC再
code#
#include<bits/stdc++.h>
#define int long long
#define P 1000000007
#define re register
#define N 1010
using namespace std;
int a[N][N],b[N][N],c[N][N],d[N][N],e[N][N];
int n1,m1,n2,m2,n3,m3,ans=0;
inline int read(){int x=0,f=1;char ch=getchar();while(!isdigit(ch)){f=ch!='-';ch=getchar();}while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return f?x:-x;}
signed main()
{
// freopen("55.in","r",stdin);
// freopen("55.out","w",stdout);
n1=read();m1=read();
for(re int i=1;i<=n1;i++)
for(re int j=1;j<=m1;j++)
a[i][j]=read();
n2=read();m2=read();
for(re int i=1;i<=n2;i++)
for(re int j=1;j<=m2;j++)
b[i][j]=read();
n3=read();m3=read();
for(re int i=1;i<=n3;i++)
for(re int j=1;j<=m3;j++)
c[i][j]=read();
for(re int i=1;i<=n2;i++)
for(re int k=1;k<=n3;k++)
for(re int j=1;j<=m3;j++)
d[i][j]=(d[i][j]+(b[i][k]*c[k][j])%P)%P;
for(re int i=1;i<=n1;i++)
for(re int k=1;k<=m1;k++)
for(re int j=1;j<=m3;j++)
e[i][j]=(e[i][j]+(a[i][k]*d[k][j])%P)%P;
for(re int i=1;i<=n1;i++)
for(re int j=1;j<=m3;j++)
ans=(ans+e[i][j])%P;
cout<<ans<<endl;
return 0;
}
/*
2 2
1 1
1 1
2 3
1 1 1
1 1 1
3 2
1 1
1 1
1 1
80
*/
T2
题面#
思路#
首先我们可以看到里面的40分是打个dij就可以水到的,但对于后面的点就没有这么好拿了。
本题需要用到状压我没学过只拿40很合理吧。
状压什么东西呢,那当然是当前点的元素种数了,没学过也不要紧,其实挺好理解。
dis数组要开二维,第二维下标就是点的编号,第一维就是当前点的元素种类的值(这个东西下面简称为元素值),这么说也许不好理解,可以理解为最大为
在遍历每一个点的时候,把当前点的元素值与(1<<(当前点的元素种类编号))进行|运算,这样你就会发现如果当前点没有遍历此元素的话,因为当前终点是此元素,就会标记成已经遍历;如果已经是遍历过的状态也就是是1的时候则不改变。
在最后的时候统计当前点的元素值转化成2进制的1的个数就可以知道遍历了多少元素了,然后取元素最多且距离尽量小的值就好了。
code#
#include<bits/stdc++.h>
#define MAXM 200010
#define MAXN 10010
#define MAXS 1<<7
using namespace std;
int n,m,dis[MAXS][MAXN],z[MAXN];//dis存放当前点元素种数的距离,z存放当前点的元素
int cnt,vis[MAXS][MAXN],head[MAXM];//vis标记当前点是入列,head链式前向星
struct sb{int w,v,next;}e[MAXM];//存边
inline void add(int u,int v,int w)//加边函数
{
e[++cnt].v=v;
e[cnt].w=w;
e[cnt].next=head[u];
head[u]=cnt;
}
int main()
{
scanf("%d%d",&n,&m);
for (int a=1;a<=n;a++)
{
char s[10];
scanf("%s",s);//"huo shui feng lei cao bing yan";
if (s[0]=='h') z[a]=0;//根据输入的字符串标记当前点的元素
else if (s[0]=='s') z[a]=1;
else if (s[0]=='f') z[a]=2;
else if (s[0]=='l') z[a]=3;
else if (s[0]=='c') z[a]=4;
else if (s[0]=='b') z[a]=5;
else if (s[0]=='y') z[a]=6;
}
for(int a=1;a<=m;a++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);//建无向图
add(v,u,w);
}
memset(dis,0x3f,sizeof dis);
dis[1<<z[1]][1]=0;//赋初值
vis[1<<z[1]][1]=1;//当前点入列
queue<pair<int,int> >q;//建队列
q.push(make_pair(1<<z[1],1));//把当前点放入队列
while(!q.empty())//只要队列不空
{
int ys=q.front().first;//取出元素数量
int u=q.front().second;//取出当前点的编号
q.pop();//弹出
vis[ys][u]=0;//标记当前点出列
for(int i=head[u];i;i=e[i].next)//枚举每一个与之相连的边
{
int v=e[i].v;//取出终点
int w=dis[ys][u]+e[i].w;//计算当前点走到v的距离
int r=ys|(1<<z[v]);//当前点右移并取或,意思是如果没有到过当前颜色就标记遍历到当前颜色
if(w<dis[r][v])//松弛操作
{
dis[r][v]=w;
if(!vis[r][v])//如果不在队列里
{
vis[r][v]=1;//标记入列
q.push(make_pair(r,v));//入列
}
}
}
}
int ans=0,res=0;//ans存放元素种数,res存放距离
for(int i=1;i<MAXS;i++)//开始遍历每一种情况
{
if(dis[i][n]==0x3f3f3f3f)continue;//如果无法遍历到就直接跳过
int j=i,k=0;//j是当前点存颜色的值
while(j)//只要j大于0
{
k+=j&1;//意思是如果这一位是1就j+1
j>>=1;//左移一位
}
if(k>ans||(k==ans&&dis[i][n]<res))//如果种类数更多或者等量种类距离更少
{
ans=k;//替换更新答案
res=dis[i][n];
}
}
printf("%d %d\n",ans,res);//输出
return 0;//好习惯
}
/*
4 3
feng
yan
lei
cao
1 2 2
2 3 10
2 4 2
*/
T3
题面#
思路#
用线段树维护区间异或和,知识盲区咕咕咕。
code#
#include<bits/stdc++.h>
#define bug cout<<"WTF?"<<'\n'
#define rson mid+1,r,rt<<1|1
#define lson l,mid,rt<<1
#define P 1000000007
#define N 100010
using namespace std;
int read(){int x=0,f=1;char ch=getchar();while(!isdigit(ch)){f=ch!='-';ch=getchar();}while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return f?x:-x;}
int n,m;
struct node
{
int l,r,cnt[32],col;//cnt存放异或的值,lr存放左右区间,col存放当前点的值
node()//初始化
{
l=r=col=0;
memset(cnt,0,sizeof(cnt));
}
void color(int v)//更新异或的值
{
col^=v;//更新异或值
for(int i=0,j=r-l+1;i<32;i++)//当前异或值的二进制最大位数
{
if(v&1)cnt[i]=j-cnt[i];
v>>=1;
}
}
int sum()//求异或和操作
{
int ans=0,v=1;
for (int i=0,j=r-l+1;i<32;i++)
{
ans=(ans+1ll*cnt[i]*(j-cnt[i])%P*v)%P;
v=v<<1;
if(v>=P)v-=P;
}
return ans;
}
}y[N<<2];
node operator+(const node &l,const node &r)
{
node ans;
ans.l=l.l;
ans.r=r.r;
for(int i=0;i<32;i++)
ans.cnt[i]=l.cnt[i]+r.cnt[i];
return ans;
}
void update(int rt){y[rt]=y[rt<<1]+y[rt<<1|1];}
void push_col(int rt)
{
if (y[rt].col)
{
y[rt<<1].color(y[rt].col);
y[rt<<1|1].color(y[rt].col);
y[rt].col=0;
}
}
void build(int l,int r,int rt)
{
// bug;
if (l==r)
{
int v=read();
y[rt].l=y[rt].r=l;
y[rt].color(v);
return;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
update(rt);
}
void modify(int l,int r,int rt,int nowl,int nowr,int v)
{
if (nowl<=l&&r<=nowr){y[rt].color(v);return;}
push_col(rt);
int mid=(l+r)>>1;
if (nowl<=mid) modify(lson,nowl,nowr,v);
if (mid<nowr) modify(rson,nowl,nowr,v);
update(rt);
}
node query(int l,int r,int rt,int nowl,int nowr)
{
if (nowl<=l && r<=nowr) return y[rt];
push_col(rt);
int mid=(l+r)>>1;
if (nowl<=mid)
{
if (mid<nowr) return query(lson,nowl,nowr)+query(rson,nowl,nowr);
else return query(lson,nowl,nowr);
}
else return query(rson,nowl,nowr);
}
int main()
{
n=read();m=read();
build(1,n,1);
for (int a=1;a<=m;a++)
{
int opt=read();
if (opt==1)
{
int l=read(),r=read(),v=read();
modify(1,n,1,l,r,v);
}
else
{
int l=read(),r=read();
printf("%d\n",query(1,n,1,l,r).sum());
}
}
return 0;
}
/*
3 3
1 2 3
2 1 3
1 1 3 3
2 1 3
*/
T4
题面#
思路#
code#
#include<bits/stdc++.h>
#define bug cout<<"WTF?"<<'\n'
#define int long long
#define N 110
using namespace std;
int n,m,a[N],b[N],c[N],k,f[N][N];//abc存放礼包能获得的点券数,商品需要的点券和购买券,f是dp数组
int cnt[N],v[21][200010],ans;//cnt存放当前购买券的方案数,v表示当购买卷有i张时,当前第j中方案的点券数
void dfs1(int x,int sma,int smb)//当前第几个,点券数,购买券数
{
if(x>k)//如果都选完了
{
cnt[smb]++;//存放当前方案
v[smb][cnt[smb]]=sma;
return ;
}
dfs1(x+1,sma+a[x],smb);//当前点选点券
dfs1(x+1,sma,smb+1);//当前点选购买券
return ;
}
int erfen(int i,int j)
{
int l=1,r=cnt[i]+1;
while(l+1!=r)
{
int mid=(l+r)>>1;
if(v[i][mid]<=j)l=mid;
else r=mid;
}
if(v[i][l]>j)l--;
return l;
}
void gent(int x,int cnt)
{
for(int i=0;i<=k;i++)
{
int pre=-1;
for(int j=0;j<=m;j++)
{
int low;
if(pre!=-1)low=pre;
else low=erfen(i,f[j][i+cnt]-x-1);
int up=erfen(i,f[j+1][i+cnt]-x-1);
pre=up;
ans+=(up-low)*j;
if(f[j+1][i+cnt]>1e6)break;
}
}
}
void dfs2(int x,int sua,int sub)
{
if(x>n)
{
int d=ans;
gent(sua,sub);
return ;
}
dfs2(x+1,sua+a[x],sub);
dfs2(x+1,sua,sub+1);
return ;
}
signed main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=m;i++)
cin>>b[i]>>c[i];
memset(f,0x3f,sizeof f);
f[0][0]=0;
for(int i=1;i<=m;i++)
for(int j=m;j>=0;j--)
for(int k=n;k>=0;k--)
f[j+1][k+c[i]]=min(f[j+1][k+c[i]],f[j][k]+b[i]);
for(int i=0;i<=m;i++)
for(int j=1;j<=n+1;j++)
f[i][j]=min(f[i][j],f[i][j-1]);
k=n/2;
dfs1(1,0,0);
for(int i=0;i<=k;i++)
sort(v[i]+1,v[i]+cnt[i]+1);
dfs2(k+1,0,0);
cout<<ans<<endl;
return 0;
}
/*
2 2
1 2
0 1
3 0
*/
作者: 北烛青澜
出处:https://www.cnblogs.com/Multitree/articles/16767246.html
本站使用「CC BY 4.0」创作共享协议,转载请在文章明显位置注明作者及出处。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!