题解:ssy的队列
题目描述
SSY是班集体育委员,总喜欢把班级同学排成各种奇怪的队形
现在班级里有
请你求出这
思路
先把题目转化一下:
给一些数和一个模数,这些数模上这个模数结果相同的分为一类
同类数不能相邻,问有多少种排列方式
易知同一类数的效果在序列中是一样的,可以将他们直接视为一种
差异只存在于数的不同大小,在最后乘上一个各个种类数字个数阶乘的乘积就行
设
可以用 hash 存每种颜色的状态,但是 map 套 vector 确实方便
转移的时候只用遍历每种状态的剩余种类进行转移就好
需要注意的是得钦定一个和
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=33,mod=1234567891;
int n,m,k,tot,a[N],b[N],sum=1;
map<vector<int>,int>f[N][N];
map<int,int>mp;
vector<int>v,t;
signed main()
{
freopen("ssy.in","r",stdin);
freopen("ssy.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++)
scanf("%lld",&b[i]);
cin>>m;
for(int i=1,x;i<=n;i++)
{
if(mp.find((b[i]%m+m)%m)==mp.end())
mp[(b[i]%m+m)%m]=++tot;
a[mp[(b[i]%m+m)%m]]++;
}
sort(a+1,a+tot+1);
for(int i=1;i<=tot;i++)
v.push_back(a[i]);
f[0][0][v]=1;
for(int i=0;i<n;i++)
for(int k=0;k<=n;k++)
for(auto it=f[i][k].begin();it!=f[i][k].end();it++)
{
v=it->first;
for(int s=0,fl=0;s<v.size();s++)
{
if(v[s]==0)
continue;
if(v[s]==k&&!fl)
{
fl=1;
continue;
}
t=v;
t[s]--;
sort(t.begin(),t.end());
f[i+1][v[s]-1][t]+=it->second;
f[i+1][v[s]-1][t]%=mod;
}
}
for(int i=1;i<=tot;i++)
{
v[i]=0;
for(int j=1;j<=a[i];j++)
sum=(sum*j)%mod;
}
printf("%lld\n",sum*f[n][0][v]%mod);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端