首先

热烈庆祝“CSP-S 2020全国开放赛前冲刺模拟训练题1”圆满结束!!!

感谢大毒瘤周指导的题目。题目还是很不错的,部分分设置的也比较合理,各种神仙随便 \(\text{AK}\) ,蒟蒻只能大呼 \(\text{NB}\) 。

Problem A

这是一道数学题。

根据周指导的题解中说明,这是一道数竞题目,但是由于我们是信竞,所以直接打一个暴力然后大胆的猜想一下就可以了。

发现这个数只能是 \(130\) 。

具体证明贴一下:

Problem B

这是一道神笔题。

我在考场上写了一个暴搜就可以过了。正解是构造 \(2\) 和 \(3\) 进制的格雷码。

所以暴搜不香吗?

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=15,MAXN=6e4+5;
int n,m,d,maxn;
struct Data{int loc[N];};
bool operator < (const Data a,const Data b)
{
for(int i=1;i<=n;++i)
if(a.loc[i]!=b.loc[i])
return a.loc[i]<b.loc[i];
return false;
}
map<Data,bool> mp;
Data way[MAXN];
bool dfs1(Data tmp,int now)
{
if(now>=maxn)
{
for(int i=1;i<=maxn;++i)
{
for(int j=1;j<=n;++j)
printf("%d ",way[i].loc[j]);
printf("\n");
}
return true;
}
Data smp;
for(int i=1;i<=n;++i)
{
smp=tmp,smp.loc[i]++;
if(smp.loc[i]<m&&!mp[smp])
{
mp[smp]=true,way[now+1]=smp;
if(dfs1(smp,now+1)) return true;
mp[smp]=false;
}
smp=tmp,smp.loc[i]--;
if(smp.loc[i]>=0&&!mp[smp])
{
mp[smp]=true,way[now+1]=smp;
if(dfs1(smp,now+1)) return true;
mp[smp]=false;
}
}
return false;
}
void subtask1()
{
Data tmp;
for(int i=1;i<=n;++i) tmp.loc[i]=0;
mp[tmp]=true,way[1]=tmp;
dfs1(tmp,1);
}
bool dfs2(Data tmp[],int l,int r,int now)
{
if(now>=maxn)
{
for(int i=1;i<=maxn;++i)
{
for(int j=1;j<=n;++j)
printf("%d ",way[i].loc[j]);
printf("\n");
}
return true;
}
Data smp[2];int L=l,R=r;
if(now%2) R--;
else L++;
smp[(now%2)^1]=tmp[(now%2)^1];
for(int i=1;i<=n;++i)
{
smp[now%2]=tmp[now%2],smp[now%2].loc[i]++;
if(smp[now%2].loc[i]<m&&!mp[smp[now%2]])
{
mp[smp[now%2]]=true;
if(now%2) way[R]=smp[now%2];
else way[L]=smp[now%2];
if(dfs2(smp,L,R,now+1)) return true;
mp[smp[now%2]]=false;
}
smp[now%2]=tmp[now%2],smp[now%2].loc[i]--;
if(smp[now%2].loc[i]>=0&&!mp[smp[now%2]])
{
mp[smp[now%2]]=true;
if(now%2) way[R]=smp[now%2];
else way[L]=smp[now%2];
if(dfs2(smp,L,R,now+1)) return true;
mp[smp[now%2]]=false;
}
}
return false;
}
void subtask2()
{
Data tmp[2];
for(int i=1;i<=n;++i) tmp[0].loc[i]=0;
mp[tmp[0]]=true,way[1]=tmp[0];
for(int i=1;i<=n;++i) tmp[1].loc[i]=m-1;
mp[tmp[1]]=true,way[maxn]=tmp[1];
dfs2(tmp,1,maxn,2);
}
int main()
{
// freopen("B.in","r",stdin);
// freopen("B.out","w",stdout);
cin>>n>>m>>d,maxn=pow(m,n);
if(n<=6||m==2) subtask1();
else subtask2();
return 0;
}

Problem C

这是一道结论题。

如果有度数小于等于3的点,就删掉这个点(和与它相关的边),先对于剩下的图构造一种方案,然后将这个点染成与他相邻的点中出现较少的颜色。

然后你发现用这个方法是可以直接过的,所以题目必定有解。

证明这个贪心周指导的题解里也很详细,贴一下:

然后在考场上有各种神仙用奇怪的随机化贪心过去了,还有什么先 \(\text{DFS}\) 再 \(\text{BFS}\) 的神仙。我乱搞能力还是太弱……

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,M=2e5+5;
int n,m;
//map<pair<int,int>,bool> mp;
struct Edge{int nxt,to;}e[M<<1];int fir[N];
void add(int u,int v,int i){e[i]=(Edge){fir[u],v},fir[u]=i;}
int deg[N],clr[N];
bool tag[N];
queue<int> q;
vector<int> ord;
int main()
{
cin>>n>>m;
for(int i=1,u,v;i<=m;++i)
{
scanf("%d%d",&u,&v);
// if(mp[make_pair(u,v)]) continue;
// mp[make_pair(u,v)]=mp[make_pair(v,u)]=true;
add(u,v,i<<1),add(v,u,i<<1|1);
deg[u]++,deg[v]++;
}
for(int i=1;i<=n;++i)
if(deg[i]<=3) q.push(i),tag[i]=true;
while(!q.empty())
{
int tmp=q.front();q.pop();
ord.push_back(tmp);//updata
for(int i=fir[tmp];i;i=e[i].nxt)
{
deg[e[i].to]--;
if(deg[e[i].to]<=3&&!tag[e[i].to])
q.push(e[i].to),tag[e[i].to]=true;
}
}
for(int i=ord.size()-1;i>=0;--i)
{
int cnt1=0,cnt2=0;
for(int j=fir[ord[i]];j;j=e[j].nxt)
cnt1+=(clr[e[j].to]==1),cnt2+=(clr[e[j].to]==2);
if(cnt1<cnt2) clr[ord[i]]=1;
else clr[ord[i]]=2;
}
for(int i=1;i<=n;++i) printf("%d ",clr[i]);
printf("\n");
return 0;
}

Problem D

这是一道套路题。

我考场上的思路是这样的,考虑我们对于一个合法的序列,如果我们交换其中两行或者两列的位置,他肯定是依旧合法的。

然后我大胆的猜测,所有的合法序列最终都一定可以变成左上方都是黑色,右下方都是白色的方案。然后我举了几个合法序列发现都对了……

然后题目就变成了问你对于所有用一条路径分割开整个矩形的方案数同时去除其中的可交换项的重复计数后的总方案数。

然后写了一个 \(O(n^3)\) 的 \(\text{DP}\) 。但是由于忘记预处理逆元了,挂了 \(20pts\) 。

考完发现自己结论是猜对的,证明贴一下:

然后发现这个东西就是斯特林数乘上一个阶乘,是可以 \(O(n^2)\) 求的(虽然我现在还不是很会)。然后用一个多项式乘法就可以满分了(我不会)。

\(70pts\) 代码如下;

#include<bits/stdc++.h>
using namespace std;
#define Lint long long
const int N=2005;
const Lint MOD=998244353;
int n,m;
Lint fac[N];
Lint f[N][N][2];
Lint sum[N][N][2];
inline int ksm(Lint x,int k)
{
Lint res=1;
for(;k;k>>=1,x=x*x%MOD)
if(k&1)res=res*x%MOD;
return res;
}
int main()
{
cin>>n>>m,fac[0]=1;
for(int i=1;i<=max(n,m);++i) fac[i]=fac[i-1]*i%MOD;
f[0][0][0]=f[0][0][1]=fac[n]*fac[m]%MOD;
for(int i=1;i<=max(n,m);++i) fac[i]=ksm(fac[i],MOD-2);
for(int i=0;i<=n;++i)
{
for(int j=0;j<=m;++j)
{
for(int k=0;k<i;++k)
f[i][j][0]+=f[k][j][1]*fac[i-k]%MOD,f[i][j][0]%=MOD;
for(int k=0;k<j;++k)
f[i][j][1]+=f[i][k][0]*fac[j-k]%MOD,f[i][j][1]%=MOD;
// printf("%d %d %lld %lld\n",i,j,f[i][j][0],f[i][j][1]);
}
}
printf("%lld\n",(f[n][m][0]+f[n][m][1])%MOD);
return 0;
}

XJOI contest 1590的更多相关文章

  1. XJOI contest 1592

    首先 热烈庆祝"CSP-S 2020全国开放赛前冲刺模拟训练题2"圆满结束!!! 感谢大毒瘤颗粒囊的题目.题目还是很不错的,部分分设置的不合理,各种神仙随便 AK ,蒟蒻只能爆零. ...

  2. XJOI 3578 排列交换/AtCoder beginner contest 097D equal (并查集)

    题目描述: 你有一个1到N的排列P1,P2,P3...PN,还有M对数(x1,y1),(x2,y2),....,(xM,yM),现在你可以选取任意对数,每对数可以选取任意次,然后对选择的某对数(xi, ...

  3. [contest 781] 9.6

    [contest 781] 9.6 - XJOI czx的温暖题... T1 军训

  4. [contest 782] 9.7

    [contest 782] 9.7 - XJOI 个人觉得温暖题啊,,,可是卡毛空间呀!!! T1 传送

  5. Programming Contest Problem Types

        Programming Contest Problem Types Hal Burch conducted an analysis over spring break of 1999 and ...

  6. hdu 4946 2014 Multi-University Training Contest 8

    Area of Mushroom Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  7. 2016 Multi-University Training Contest 2 D. Differencia

    Differencia Time Limit: 10000/10000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tot ...

  8. 2016 Multi-University Training Contest 1 G. Rigid Frameworks

    Rigid Frameworks Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  9. hdu-5988 Coding Contest(费用流)

    题目链接: Coding Contest Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Ot ...

随机推荐

  1. 【java从入门到精通】day-06-基本运算符-自增自减运算符

    1.运算符 java语言支持如下运算符: 算术运算符:+,-,*,/,%,++,-- 赋值运算符:= 关系运算符:>,<,>=,<=,==,!=,instanceof 逻辑运算 ...

  2. Java的注释-标识符和关键字

    1.Java注释 单行注释 多行注释 文档注释 代码示例 public class Hello{    public static void main(String[] args) {         ...

  3. hive简单的项目实战

    解压user.zip [root@hadoop1 test]# unzip user.zip -d /test/bigdatacase/dataset Archive: user.zip inflat ...

  4. 详解scanf与getchar

    原文: (https://www.myjinji.top/articles/2020/07/22/1595399358246.html)[https://www.myjinji.top/article ...

  5. 一个List按照某个size分割为多个小的List

    针对于List的size比较大,使用多线程处理任务时,可以将List分割为一个一个比较小的任务单元进行处理. 例如集合大小:645,按照100分割,会将集合分割为6个size为100的集合和一个siz ...

  6. Java web 自动备份数据库和log4j日志

    利用监听自动备份 web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns: ...

  7. Android10_原理机制系列_Activity窗口添加到WMS过程

    前言 首先看一个Android界面的布局层次结构,最直观的看一下: 我们能清晰看到,这个界面分成了3部分:顶部状态栏(statusbar).底部导航栏(navigationbar).应用界面. 题外话 ...

  8. PicGo+jsDelivr+GitHub搭建免费图床,Typora使用图床

    Github配置 首先,创建一个GitHub账号 然后添加一个仓库 创建完后点头像,Setting 然后点击Developer settings 然后点击Personal access tokens ...

  9. CorelDRAW中的合并和群组功能

    在设计过程中,对象就是我们进行操作的主体,这个操作主体可以是单个对象,也可以是多个对象,在有多个对象要进行处理时,就需要用到类似CorelDRAW里的合并和群组这两个功能了. 一.合并与拆分 合并功能 ...

  10. 使用Mac清理工具CleanMyMac对Mac电脑进行维护

    CleanMyMac是Mac系统下的一款苹果电脑清理软件,同时也是一款优秀的电脑维护软件,它能通过用户手动运行CleanMyMac内置脚本文件,释放电脑内存,帮助电脑缓解卡顿现象,保证电脑的良好持续运 ...