2023.4.12拷逝
T1 seq
首先这道题要注意对题意的理解,子序列的意思是子集,而不是子区间。
我们可以将序列从小到大排序。排序后,如果一个子序列只有
由此可知,
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const long long mod=998244353;
long long p[1000005],n,a[1000005],ans,sum;
int main(){
freopen("seq.in","r",stdin);
freopen("seq.out","w",stdout);
scanf("%lld",&n);
for(int i=1;i<=n;++i)
scanf("%lld",&a[i]);
sort(a+1,a+n+1);
p[0]=1;
for(int i=1;i<=n;++i)
p[i]=p[i-1]*2%mod;
for(int i=1;i<=n;++i){
sum=(sum*2%mod+a[i-1]%mod)%mod;
ans=(ans+a[i]*sum%mod)%mod;
ans=(ans+a[i]*a[i]%mod)%mod;
}
printf("%lld\n",ans);
fclose(stdin);fclose(stdout);
return 0;
}
T2 game
图的形态只有两种,一种是初始形态,另一种是边权全部取反的形态,所以可以考虑分层图。
第一层图只将权值为
最后在这个分层图上跑
#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
int n,m,k,u,v,w,p,tot,nxt[8000005],ver[8000005],head[8000005],hav[4000005],dis[4000005],ok;
struct node{
int f,step;
};queue <node> q;
void add(int x,int y){
nxt[++tot]=head[x];head[x]=tot;
ver[tot]=y;
}
int main(){
//freopen("game.in","r",stdin);
//freopen("game.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;++i){
scanf("%d%d%d",&u,&v,&w);
if(w)
add(u,v),add(v,u);
else
add(u+n,v+n),add(v+n,u+n);
}
for(int i=1;i<=k;++i)
scanf("%d",&p),hav[p]=hav[p+n]=1;
for(int i=2;i<=n*2;++i)
dis[i]=1e9;
q.push((node){1,0});
while(!q.empty()){
node x=q.front();q.pop();
//cout<<x.f<<endl;
if(x.step>dis[x.f])
continue;
if(x.f==n||x.f==n*2){
printf("%d\n",min(dis[n],dis[n*2]));
ok=1;
break;
}
for(int i=head[x.f];i;i=nxt[i])
if(x.step+1<dis[ver[i]]){
dis[ver[i]]=x.step+1;
q.push((node){ver[i],x.step+1});
}
if(hav[x.f]){
if(x.f>n) x.f-=n;
else x.f+=n;
if(x.step>dis[x.f])
continue;
for(int i=head[x.f];i;i=nxt[i])
if(x.step+1<dis[ver[i]]){
dis[ver[i]]=x.step+1;
q.push((node){ver[i],x.step+1});
}
}
}
if(!ok)
printf("-1\n");
fclose(stdin);fclose(stdout);
return 0;
}
T3 count
看到这道题,可以考虑质因数分解。
先考虑只有一种质因数的数。设
考虑如何求这个数组。如果倒数第二个数也是
对于一般形式的数,应该怎么求呢?先给结论:如果一个数
综上,我们可以先求出
#include<iostream>
#include<cstdio>
using namespace std;
long long f[25][200005],n,m,tot,sum[200005],ans,p[200005];bool ok[200005];
//f[i][j]:i阶等差数列第j项
const long long mod=998244353;
int main(){
//freopen("count.in","r",stdin);
//freopen("count.out","w",stdout);
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;++i)
f[0][i]=1;
for(int i=1;i<=20;++i)
for(int j=1;j<=n;++j)
f[i][j]=(f[i][j-1]+f[i-1][j])%mod;
//for(int i=1;i<=20;++i,cout<<endl)
// for(int j=1;j<=n;++j)
// cout<<f[i][j]<<" ";
for(int i=2;i*i<=m;++i)
if(!ok[i]){
p[++tot]=i;
for(int j=i+i;j*j<=m;j+=i)
ok[j]=1;
}
//cout<<tot<<endl;
//for(int i=1;i<=tot;++i)
// cout<<p[i]<<" ";cout<<endl;
for(int i=1;i<=m;++i)
sum[i]=1;
for(int i=2;i<=m;++i){
int tmp=i,cnt;
//if(i%10000==0)cout<<i<<endl;
for(int j=1;tmp>1&&j<=tot;++j){
cnt=0;
while(tmp%p[j]==0)
tmp/=p[j],++cnt;
sum[i]=(sum[i]*f[cnt][n])%mod;
}
if(tmp>1)
sum[i]=(sum[i]*f[1][n])%mod;
}
for(int i=1;i<=m;++i)
ans=(ans+sum[i])%mod;
printf("%lld\n",ans);
fclose(stdin);fclose(stdout);
return 0;
}
T4 gift
如果
设
我用的是记忆化搜索,当然也可以用
#include<iostream>
#include<cstdio>
using namespace std;
long long n,m,ans,stk[50005],sum[50005],c[5005][5005],tot,f[5005][25];bool ok[5005][25];
const long long mod=998244353;//f[i][j]表示二进制前j位拼出i的方案数
long long dfs(int x,int y){//二进制第x位(2^(x-1)),还剩下y
if(ok[y][x])
return f[y][x];
if(!y)
return f[y][x]=1;
if(x==0)
return f[y][x]=0;
for(int j=0;j<=n&&y-j*(1<<(x-1))>=0;j+=2){
f[y][x]=(f[y][x]+c[n][j]*dfs(x-1,y-j*(1<<(x-1)))%mod)%mod;
}
ok[y][x]=1;
return f[y][x];
}
int main(){
freopen("gift.in","r",stdin);
freopen("gift.out","w",stdout);
sum[0]=1;
scanf("%lld%lld",&n,&m);
for(int i=0;i<=n;++i)
c[i][0]=1;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
printf("%lld\n",dfs(14,m));
fclose(stdin);fclose(stdout);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】