2023.7.3测试
T1 边的方向
一个无重边、自环的无向图,现在给每条边标上方向,要求每个点有且只有一条出边,求有多少种合法的方案,答案模
不算很难的题
若
之后把所有度数为
如果环里套环,即某个点的度数不为
#include<bits/stdc++.h>
#define LL long long
#define mp make_pair
using namespace std;
const int N=200010;
const LL MOD=998244353;
int n,m,deg[N],cnt;
vector < pair<int,int> > g[N];
bool e[N],flag[N],vis[N];
LL ans=1;
void dfs(int x)
{
vis[x]=1;
for(int i=0; i<g[x].size(); i++)
{
if(!e[g[x][i].second])
{
int y=g[x][i].first;
if(!vis[y] && !flag[y])
dfs(y);
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++)
{
int x,y;
scanf("%d%d",&x,&y);
g[x].push_back(mp(y,i));
g[y].push_back(mp(x,i));
deg[x]++; deg[y]++;
}
if(m<n)
{
printf("0");
return 0;
}
for(int i=1; i<=n; i++)
{
if(!deg[i])
{
printf("0");
return 0;
}
}
for(int i=1; i<=n; i++)
{
if(deg[i]==1)
{
int x=i;
do
{
int y=0,z=0;
for(int j=0; j<g[x].size(); j++)
{
if(!e[g[x][j].second])
{
y=g[x][j].first; z=g[x][j].second;
break;
}
}
deg[x]--; deg[y]--;
e[z]=1; flag[x]=1;
if(deg[y]==0 && !flag[y])
{
printf("0");
return 0;
}
x=y;
}while(deg[x]==1);
}
}
for(int i=1; i<=n; i++)
{
if(!flag[i] && deg[i]!=2)
{
printf("0");
return 0;
}
}
for(int i=1; i<=n; i++)
{
if(!flag[i] && !vis[i])
dfs(i),cnt++;
}
for(int i=1; i<=cnt; i++)
(ans*=2)%=MOD;
printf("%lld",ans);
return 0;
}
T2 游戏得分
有长度为
考场上努力搞出来了(被薄纱)
首先可感觉到排列的变换过程中会存在一些分组,组内的数字不断交换,但组与组之间没有联系。而每个组内部一次循环所需的操作数是数字的个数,最后的操作次数就是所有组操作次数的最小公倍数
由于数据比较小,所以我们可以暴力地从大到小去递归枚举组内的数字数量。记状态
那么,我们枚举分组的组数
更新
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=60;
const LL MOD=998244353;
int n,a[N];
LL k,ans,tot[N],fac[N],inv[N];
bool v[N];
LL gcd(LL a,LL b)
{
if(b==0)
return a;
return gcd(b,a%b);
}
LL lcm(LL a,LL b)
{
return a*b/gcd(a,b);
}
LL ksm(LL x,LL y)
{
LL res=1;
while(y)
{
if(y&1)
res=res*x%MOD;
x=x*x%MOD;
y>>=1;
}
return res;
}
void prework()
{
fac[0]=inv[0]=1;
for(int i=1; i<=n; i++)
{
fac[i]=(fac[i-1]*i)%MOD;
inv[i]=ksm(fac[i],MOD-2);
}
}
LL C(int x,int y)
{
if(y>x)
return 0;
return fac[x]*inv[x-y]%MOD*inv[y]%MOD;
}
LL count(int t,int x)
{
LL res=1;
for(int i=t*x; i>=x; i-=x)
(res*=C(i,x))%=MOD;
(res*=inv[t])%=MOD;
return res;
}
void dfs(int step,int s,LL pre,LL cur) //step枚举到的层数,s现在还有多少人,pre之前的贡献,cur当前最小公倍数
{
if(s==0)
{
(ans+=1LL*pre*ksm(cur,k)%MOD)%=MOD;
return;
}
if(step==0)
return;
for(int i=0; i*step<=s; i++)
dfs(step-1,s-i*step,pre*count(i,step)%MOD*ksm(fac[step-1],i)%MOD*C(s,i*step)%MOD,lcm(cur,i==0?cur:(LL)step));
}
int main()
{
scanf("%d%lld",&n,&k);
prework();
dfs(n,n,1,1);
printf("%lld",ans);
return 0;
}
T3 Group Projects
又又又是插入
显然要排序(我也不知道怎么显然),将
状态的第一维显然是考虑到第
将
-
当
单独成组时 -
当
作为组的中间时,可以随便选一个插入 -
当
作为一个组的结尾时,组数会 -
当
作为一个组的开头时,组数要
#include<bits/stdc++.h>
using namespace std;
const int N=210,M=1010;
const int MOD=1e9+7;
int n,m,a[N],f[N][N][M];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
sort(a+1,a+1+n);
f[0][0][0]=1;
for(int i=1; i<=n; i++)
{
for(int j=0; j<=n; j++)
{
int p=(a[i]-a[i-1])*j;
for(int k=0; k+p<=m; k++)
{
(f[i][j][k+p]+=1LL*f[i-1][j][k]*(j+1)%MOD)%=MOD;
if(j!=n)
(f[i][j+1][k+p]+=f[i-1][j][k])%=MOD;
if(j!=0)
(f[i][j-1][k+p]+=1LL*f[i-1][j][k]*j%MOD)%=MOD;
}
}
}
int ans=0;
for(int i=0; i<=m; i++)
(ans+=f[n][0][i])%=MOD;
printf("%d",ans);
return 0;
}
T4 卡片 查看测评数据信息
有
重复以下操作
1、针对当前剩下的卡片,你可以对最左边的
2、最左边的
若最终剩下的
输出最大总得分。
输出
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】