2022.7.30 模拟赛
2022.7.30 模拟赛#
序列#
看到大的一直减去小的,很容易想到辗转相减法求 的公式:
显然我们可以把问题转变成:变成所有非最小值辗转相除最小值 (模仿求 的过程)
由于单次辗转相除求 是 的 ( 表示最大数)
那么显然对整个序列求一遍时间复杂度就是 的
当然这个过程实际上相当于求一边所有数的
所以我为什么没想到这一点而是写了更长的代码
code:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int n;
int a[100005];
inline int solve(int &x){
for(int i=x-1;i>=1;--i) a[i]=a[i]%a[x];
for(int i=x+1;i<=n;++i) a[i]=a[i]%a[x];
int mn=1e9+1,cnt=0;
for(int i=1;i<=n;++i){
if(!a[i]) continue;
++cnt;
if(mn>a[i]){
mn=a[i];
x=i;
}
}
return cnt>1;
}
signed main(){
n=read();
int mn=1e9+1,id;
for(int i=1;i<=n;++i){
a[i]=read();
if(a[i]<mn){
mn=a[i];
id=i;
}
}
while(1){
if(!solve(id)) break;
}
printf("%d\n",a[id]);
}
任意模数快速插值#
code:
#include <bits/stdc++.h>
using namespace std;
#define lsp p<<1
#define rsp p<<1|1
#define add(x,y) ({int xx=x+y;xx<M?xx:xx-M;})
const int N=5e5+5,M=998244353;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int n,ans;
struct Tree{
int s,d1,x1,d2,x2,s1,s2,t1,t2;
}t[N*4];
inline void Update1(int p,int l,int r,int w){
t[p].d1=t[p].x1=t[p].t1=w;
t[p].s1=1ll*w*(r-l+1)%M;
t[p].s=1ll*w*t[p].s2%M;
}
inline void Update2(int p,int l,int r,int w){
t[p].d2=t[p].x2=t[p].t2=w;
t[p].s2=1ll*w*(r-l+1)%M;
t[p].s=1ll*w*t[p].s1%M;
}
inline void push_down(int p,int l,int r){
int mid=l+r>>1;
if(t[p].t1!=-1){
Update1(lsp,l,mid,t[p].t1);
Update1(rsp,mid+1,r,t[p].t1);
}
if(t[p].t2!=-1){
Update2(lsp,l,mid,t[p].t2);
Update2(rsp,mid+1,r,t[p].t2);
}
t[p].t1=t[p].t2=-1;
}
inline void update1(int p,int l,int r,int L,int R,int w){
if(t[p].x1>=w) return;
if(L<=l&&r<=R&&t[p].d1<w) return Update1(p,l,r,w);
int mid=l+r>>1;
push_down(p,l,r);
if(L<=mid) update1(lsp,l,mid,L,R,w);
if(R>mid) update1(rsp,mid+1,r,L,R,w);
t[p].d1=max(t[lsp].d1,t[rsp].d1);
t[p].x1=min(t[lsp].x1,t[rsp].x1);
t[p].s1=add(t[lsp].s1,t[rsp].s1);
t[p].s=add(t[lsp].s,t[rsp].s);
}
inline void update2(int p,int l,int r,int x,int y,int w){
if(t[p].d2<=w) return;
if(x<=l&&r<=y&&t[p].x2>w) return Update2(p,l,r,w);
int mid=l+r>>1;push_down(p,l,r);
if(x<=mid) update2(lsp,l,mid,x,y,w);
if(y>mid) update2(rsp,mid+1,r,x,y,w);
t[p].d2=max(t[lsp].d2,t[rsp].d2);
t[p].x2=min(t[lsp].x2,t[rsp].x2);
t[p].s2=add(t[lsp].s2,t[rsp].s2);
t[p].s=add(t[lsp].s,t[rsp].s);
}
inline int query(int p,int l,int r,int L,int R){
if(L<=l&&r<=R) return t[p].s;
int mid=l+r>>1,res=0;
push_down(p,l,r);
if(L<=mid) res=query(lsp,l,mid,L,R);
if(R>mid) res=add(res,query(rsp,mid+1,r,L,R));
return res;
}
signed main(){
n=read();
for (int i=n*4;i>=1;--i)
t[i].d2=t[i].x2=1e9,t[i].t1=t[i].t2=-1;
for (int i=1;i<=n;++i){
int x=read();
update1(1,1,n,1,i,x);
update2(1,1,n,1,i,x);
if((ans+=query(1,1,n,1,i))>=M) ans-=M;
}
printf("%d\n",ans);
return 0;
}
快递#
第一想法网络流,但是好像不可做
由于 很小,想的是状压
但是发现自己想不出 的顺序,于是干脆不想了,写的状压记忆化搜索
先跑一遍 求出两两之间的最短路
这里设的 表示到达 ,当前手里的快递为 ,已经送完的快递为 的最小时间
那么有 (条件没写):
第一个转移表示拿,第二个转移表示送
还有一些细节看代码
code:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=21;
const int inf=1e9;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int n,m,q,ans,mx;
int g[N][N];
int f[N][1<<10][1<<10];
int s[N],t[N],l[N],r[N];
int c[1<<10];
inline void floyd(){
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j){
if(i==j) continue;
for(int k=1;k<=n;++k){
if(i==k||j==k) continue;
g[j][k]=min(g[j][k],g[j][i]+g[i][k]);
}
}
}
inline void calc(int x){
for(int i=0;i<q;++i)
c[x]+=(x&(1<<i))!=0;
}
inline void dfs(int x,int st,int ed,int T){
//cout<<x<<" "<<st<<" "<<ed<<" "<<T<<endl;
if(f[x][st][ed]<=T||T>mx) return;
f[x][st][ed]=T;
ans=max(ans,c[ed]);
for(int i=0;i<q;++i){
if((st&(1<<i))||(ed&(1<<i))) continue;
dfs(s[i],st|(1<<i),ed,max(l[i],T+g[x][s[i]]));
}
for(int i=0;i<q;++i){
if(((st&(1<<i))==0)||T+g[x][t[i]]>r[i]) continue;
dfs(t[i],st^(1<<i),ed|(1<<i),T+g[x][t[i]]);
}
}
signed main(){
n=read(),m=read(),q=read();
for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) g[i][j]=inf;
for(int i=1;i<=n;++i) g[i][i]=0;
for(int i=1;i<=n;++i)
for(int j=0;j<(1<<10);++j)
for(int k=0;k<(1<<10);++k)
f[i][j][k]=inf;
for(int i=0;i<(1<<10);++i) calc(i);
while(m--){
int x=read(),y=read(),z=read();
g[x][y]=min(g[x][y],z);
}
floyd();
for(int i=0;i<q;++i){
s[i]=read(),t[i]=read(),l[i]=read(),r[i]=read();
mx=max(mx,r[i]);
}
dfs(1,0,0,0);
printf("%d\n",ans);
}
任意模数多项式乘法逆#
神仙题,赛时无人
然而我也不会啊
这是题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!