2023.11.14测试
T1 简单的题
给三个数
把
设
但是现在还要求必须选某个数
UPD:获得
code
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
#define LL long long
using namespace std;
bool Mbe;
const int N=800,QQ=5010,SS=(1<<8)+10;
const int MOD=998244853;
int n,G,L,des,Q,S,q[QQ],ans[N];
int a[N],d[N],m;
int p[N][10],cnt,legal[N][2];
int f[N][SS][SS],g[N][SS][SS];
map <int,int> desp;
bool isque[N];
void prework()
{
for(int i=1; i*i<=L; i++)
{
if(L%i==0)
{
if(i%G==0 && i<=n)
a[++m]=i;
if(i*i!=L && (L/i)%G==0 && L/i<=n)
a[++m]=L/i;
}
}
sort(a+1,a+1+m);
for(int i=1; i<=m; i++)
d[i]=a[i]/G;
}
void divide(int x,int i)
{
for(int j=2; j*j<=x; j++)
{
if(x%j==0)
{
if(i==0)
desp[j]=++cnt;
int id=desp[j];
while(x%j==0)
p[i][id]++,x/=j;
}
}
if(x>1)
{
if(i==0)
desp[x]=++cnt;
p[i][desp[x]]++;
}
}
void work(int i)
{
for(int j=1; j<=cnt; j++)
{
if(p[i][j]==p[0][j])
legal[i][0]^=(1<<j-1);
if(p[i][j]==0)
legal[i][1]^=(1<<j-1);
}
}
void SOS_DP()
{
for(int i=1; i<=cnt; i++)
for(int s=0; s<=S; s++)
if(!(s&(1<<i-1)))
for(int t=0; t<=S; t++)
for(int j=1; j<=m; j++)
(g[j][s][t]+=g[j][s|(1<<i-1)][t])%=MOD;
for(int i=1; i<=cnt; i++)
for(int t=0; t<=S; t++)
if(!(t&(1<<i-1)))
for(int s=0; s<=S; s++)
for(int j=1; j<=m; j++)
(g[j][s][t]+=g[j][s][t|(1<<i-1)])%=MOD;
}
int solve(int i)
{
int res=0;
for(int s=0; s<=S; s++)
{
for(int t=0; t<=S; t++)
{
int ss=s|legal[i][0],tt=t|legal[i][1];
(res+=1LL*f[i-1][s][t]*g[i+1][S^ss][S^tt]%MOD)%=MOD;
}
}
return res;
}
bool Med;
int main()
{
freopen("easy.in","r",stdin);
freopen("easy.out","w",stdout);
// fprintf(stderr, "%.3lfMB\n",(&Mbe-&Med)/1048576.000);
scanf("%d%d%d%d",&n,&G,&L,&Q);
for(int i=1; i<=Q; i++)
scanf("%d",&q[i]);
if(L%G!=0)
{
for(int i=0; i<=Q; i++)
puts("0");
return 0;
}
prework();
divide(des=L/G,0);
for(int i=1; i<=m; i++)
{
divide(d[i],i);
work(i);
}
for(int i=1; i<=Q; i++)
{
int cur=lower_bound(a+1,a+1+m,q[i])-a;
if(a[cur]!=q[i])
continue;
isque[cur]=1;
}
f[0][0][0]=1; S=(1<<cnt)-1;
for(int i=0; i<m; i++)
{
for(int s=0; s<=S; s++)
{
for(int t=0; t<=S; t++)
{
(f[i+1][s|legal[i+1][0]][t|legal[i+1][1]]+=f[i][s][t])%=MOD;
(f[i+1][s][t]+=f[i][s][t])%=MOD;
}
}
}
g[m+1][0][0]=1;
for(int i=m+1; i>1; i--)
{
for(int s=0; s<=S; s++)
{
for(int t=0; t<=S; t++)
{
(g[i-1][s|legal[i-1][0]][t|legal[i-1][1]]+=g[i][s][t])%=MOD;
(g[i-1][s][t]+=g[i][s][t])%=MOD;
}
}
}
SOS_DP();
for(int i=1; i<=m; i++)
{
if(!isque[i])
continue;
ans[i]=solve(i);
}
printf("%d\n",f[m][S][S]);
for(int i=1; i<=Q; i++)
{
int cur=lower_bound(a+1,a+1+m,q[i])-a;
if(a[cur]!=q[i])
puts("0");
else
printf("%d\n",ans[cur]);
}
return 0;
}
T4 疯癫兄弟
一个很经典但是想不到的 Trick,把区间
一开始的差分序列上有若干个
根据「哥德巴赫猜想」,任何一个
贪心的考虑,我们要让奇质数的匹配最多,发现这一定是一奇一偶之间作差,于是建出二分图,求出最大匹配,再加上其它的贡献即可。
这种差分和前缀和、区间与单点之间的转化还是蛮常见的。
code
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10,NN=1e7+10,M=1e7+10,INF=1e9;
int n,m,a[N<<1],b[NN],cnt[2];
int s,t,maxflow,d[N<<1];
int head[N<<1],nxt[M<<1],ver[M<<1],edge[M<<1],now[N<<1],tot=1;
void add(int x,int y,int z)
{
ver[++tot]=y; edge[tot]=z; nxt[tot]=head[x]; head[x]=tot;
ver[++tot]=x; edge[tot]=0; nxt[tot]=head[y]; head[y]=tot;
}
bool bfs()
{
memset(d,0,sizeof(d));
queue <int> q;
q.push(s); d[s]=1;
now[s]=head[s];
while(q.size())
{
int x=q.front(); q.pop();
for(int i=head[x]; i; i=nxt[i])
{
int y=ver[i];
if(edge[i] && !d[y])
{
d[y]=d[x]+1;
now[y]=head[y];
q.push(y);
if(y==t)
return 1;
}
}
}
return 0;
}
int dinic(int x,int flow)
{
if(x==t)
return flow;
int rest=flow;
for(int &i=now[x]; i && rest; i=nxt[i])
{
int y=ver[i];
if(edge[i] && d[y]==d[x]+1)
{
int k=dinic(y,min(rest,edge[i]));
if(k<=0)
d[y]=0;
edge[i]-=k;
edge[i^1]+=k;
rest-=k;
if(rest<=0)
break;
}
}
return flow-rest;
}
void Dinic()
{
int flow=0;
while(bfs())
while(flow=dinic(s,INF))
maxflow+=flow;
}
bool isprime(int x)
{
if(x==1)
return 0;
if(x==2)
return 1;
for(int i=2; i*i<=x; i++)
if(x%i==0)
return 0;
return 1;
}
int main()
{
freopen("crazy.in","r",stdin);
freopen("crazy.out","w",stdout);
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
int x;
scanf("%d",&x);
b[x]^=1; b[x+1]^=1;
}
for(int i=0; i<=1e7+1; i++)
if(b[i])
a[++m]=i,cnt[i&1]++;
for(int i=1; i<=m; i++)
for(int j=i+1; j<=m; j++)
if(((a[j]-a[i])&1) && isprime(a[j]-a[i]))
{
if(a[i]&1)
add(i,j,1);
else
add(j,i,1);
}
s=0; t=m+1;
for(int i=1; i<=m; i++)
{
if(a[i]&1)
add(s,i,1);
else
add(i,t,1);
}
Dinic();
int ans=maxflow;
int tmp[2]={(cnt[0]-ans)/2*2,(cnt[1]-ans)/2*2};
ans+=tmp[0]+tmp[1];
if(maxflow+tmp[0]!=cnt[0])
ans+=3;
printf("%d\n",ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?