7.1 NOI模拟赛 计数问题 dp


还是可以想出来的题目 不过考场上没有想出来 要 引以为戒。
初看觉得有点不可做 10分给到了爆搜。
考虑第一个特殊情况 B排列为1~m.
容易发现A排列中前m个数字 他们之间不能产生交换 且 第k个数字要交换到后面的m+1~n这些数字的时候 k~m的数字都要进行交换才行。
那么直接枚举有多少个数字到后面了 组合数可以解决 考虑剩下的那些空位怎么办。
其实就是要求出 \(f_i\) 其表示满足题目条件的i个数的排列的个数.
考虑递推 容易发现\(f_0=1,f_1=1\) 对于\(f_i\)考虑第i个数字不换 那么为\(f_{i-1}\)换的话有i-1种方法 对应的方案为\((i-1)\cdot f_{i-2}\)
综上可以得到\(f_i=f_{i-1}+(i-1)\cdot f_{i-2}\)
这样结合上面的dfs就可以获得30分了。
考虑另外一种递推的模型 可以发现m在第一个 那么就要想办法将m换到第一个。
显然 m可以不动 那么剩下的m-1个数字就要放到后面了。
m可以直接和1交换 那么剩下的m-2个数字要放到后面。
m还可以和后面的进行交换 其实就是m个数字放到后面。
三种情况分别讨论即可。结合上面的两种方法就可以得到50分了。具体细节看代码。
上午也只推到这里。因为感觉正解比较难 所以就每有一直探索下去 其实可以继续走下去。
考虑正解:综上其实可以发现 m个数全部扔到后面是一定合法的,那么其实就是考虑有多少个数字可以被扔到前面。
如果有k个数字在后面 那么前面这s=m-k个数字就应该在前面 且他们不能和后面的k个数字存在交换。
这样就要求他们是一个合法排列 容易想到合法情况最多只有一种 这点容易证明。
也就是说此时只需要判断s个数字放到前面是否合法 即满足题目中的条件。
可以暴力安排位置 因为第一个要放到数值最小的位置上去 这样暴力放然后再check即可。
复杂度\(m^2+n\)
code
//#include<bits\stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 100000000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define gc(a) scanf("%s",a+1)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE int i=n;i>=p;--i)
#define vep(p,n,i) for(RE int i=p;i<n;++i)
#define pii pair<int,int>
#define mk make_pair
#define RE register
#define P 1000000007
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-8
#define sq sqrt
#define mod 1000000007
#define S second
#define F first
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
RE int x=0,f=1;RE char ch=getc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
return x*f;
}
const int MAXN=30010,maxn=10000010;
int n,m,ans;
int a[MAXN],b[MAXN];
int vis[MAXN],f[maxn],fac[maxn],inv[maxn];
inline int ksm(int b,int p)
{
int cnt=1;
while(p)
{
if(p&1)cnt=(ll)cnt*b%mod;
b=(ll)b*b%mod;p=p>>1;
}
return cnt;
}
inline void dfs(int x)
{
if(x==n+1)
{
int cnt=1;
rep(1,n,i){if(a[a[i]]!=i)return;if(a[i]==b[cnt])++cnt;}
if(cnt>m)
{
++ans;
//rep(1,n,i)cout<<a[i]<<' ';
//cout<<endl;
}
return;
}
rep(1,n,i)
{
if(vis[i])continue;
a[x]=i;vis[i]=1;
dfs(x+1);
vis[i]=0;
}
}
inline int C(int a,int b){return (ll)fac[a]*inv[b]%mod*inv[a-b]%mod;}
inline int check()
{
rep(2,m,i)if(b[i]!=i-1)return 0;
return 1;
}
inline void prepare()
{
f[0]=1;fac[0]=1;
rep(1,n,i)
{
fac[i]=(ll)fac[i-1]*i%mod;
f[i]=(f[i-1]+(ll)f[i-2]*(i-1))%mod;
}
inv[n]=ksm(fac[n],mod-2);
fep(n-1,0,i)inv[i]=(ll)inv[i+1]*(i+1)%mod;
}
int main()
{
freopen("1.in","r",stdin);
//freopen("ya.out","w",stdout);
get(n);get(m);int flag=0;
if(n<m){put(0);return 0;}
rep(1,m,i)
{
get(b[i]);
if(b[i]!=i)flag=1;
}
if(n<=10)
{
dfs(1);put(ans);
return 0;
}
prepare();
if(m==1){put(f[n]);return 0;}
if(n==m)
{
rep(1,m,i)if(b[b[i]]!=i){put(0);return 0;}
put(1);return 0;
}
if(!flag)
{
int ww=min(m,n-m);
rep(0,ww,i)ans=(ans+(ll)C(n-m,i)*f[n-m-i])%mod;
put(ans);return 0;
}
if(b[1]==m&&check())
{
if(n>=2*m-2)//和1交换.
ans=(ll)f[n-2*m+2]*C(n-m,m-2)%mod;
if(n>=2*m-1)//不动.
ans=(ans+(ll)f[n-2*m+1]*C(n-m,m-1))%mod;
if(n>=2*m)//交换.
ans=(ans+(ll)f[n-2*m]*C(n-m,m))%mod;
put(ans);
}
else
{
if(n>=2*m)ans=(ans+(ll)f[n-2*m]*C(n-m,m))%mod;
rep(1,m,i)//枚举前m个位置
{
if(n<2*m-i)continue;
int flag=0,ww=0;
vis[b[i]]=1;
rep(1,i,j)
{
++ww;
while(!vis[ww])++ww;
a[b[j]]=ww;
}
rep(1,m,j)if(vis[j]&&a[a[j]]!=j){flag=1;break;}
if(!flag)ans=(ans+(ll)f[n-2*m+i]*C(n-m,m-i))%mod;
//cout<<flag<<endl;
}
put(ans);
}
return 0;
}
7.1 NOI模拟赛 计数问题 dp的更多相关文章
- 6.28 NOI模拟赛 好题 状压dp 随机化
算是一道比较新颖的题目 尽管好像是两年前的省选模拟赛题目.. 对于20%的分数 可以进行爆搜,对于另外20%的数据 因为k很小所以考虑上状压dp. 观察最后答案是一个连通块 从而可以发现这个连通块必然 ...
- NOI模拟赛 Day1
[考完试不想说话系列] 他们都会做呢QAQ 我毛线也不会呢QAQ 悲伤ING 考试问题: 1.感觉不是很清醒,有点困╯﹏╰ 2.为啥总不按照计划来!!! 3.脑洞在哪里 4.把模拟赛当作真正的比赛,紧 ...
- [10.18模拟赛] 序列 (DP)
[10.18模拟赛] 序列 题目描述 山山有一个整数序列s1,s2,-,sn,其中1≤si≤k. 求出有多少个准确移除m个元素后不同的序列.答案模(1e9+7) 输入 输入包括几个测试用例,并且由文件 ...
- 7.12 NOI模拟赛 生成树 装压dp vector装压
LINK:生成树 这场比赛我打的真失败 T3是比较容易的 却一直刚 那道"数论" 10分其实搜一下全排列. 30分容易想到对边进行装压dp. 不过存在一些细节 可以对于一个连通块的 ...
- 7.12 NOI模拟赛 探险队 期望 博弈 dp 最坏情况下最优策略 可并堆
LINK:探险队 非常难的题目 考试的时候爆零了 完全没有想到到到底怎么做 (当时去刚一道数论题了. 首先考虑清楚一件事情 就是当前是知道整张地图的样子 但是不清楚到底哪条边断了. 所以我们要做的其实 ...
- 7.11 NOI模拟赛 graph 生成函数 dp 多项式
LINK:graph HDU题库里的原题 没做过自闭. 考虑dp 设\(f_{i,j}\)表示前i个点构成j个联通块是树的方案数. 对于一次询问答案即为\(\sum_{j}f_{n,j}j^k\) 考 ...
- 7.1 NOI模拟赛 dp floyd
这是一道非常垃圾的题目 且 数据范围简直迷惑选手.. 可以发现 题目中有 边权递增 边的条数 所有边权值不同 最小边权和等条件. 看起来很难做 一个想法 边权递增+边的1的权值都不相同可以想到 关系存 ...
- 7.9 NOI模拟赛 C.走路 背包 dp 特异性
(啊啊啊 什么考试的时候突然降智这题目硬生生没想出来. 容易发现是先走到某个地方 然后再走回来的 然后在倒着走的路径上选择一些点使得最后的得到的最多. 设\(f_{i,j}\)表示到达i这个点选择的价 ...
- NOI 模拟赛 #2
得分非常惨惨,半个小时写的纯暴力 70 分竟然拿了 rank 1... 如果 OYJason 和 wxjor 在可能会被爆踩吧 嘤 T1 欧拉子图 给一个无向图,如果一个边集的导出子图是一个欧拉回路, ...
随机推荐
- 特殊方格棋盘【状压DP】
特殊方格棋盘[状压DP] 讲真状压DP这个东西只不过是有那么亿丢丢考验心态罢了(确信) 先从板子题说起,另加一些基础知识 题目描述 在的方格棋盘上放置n 个车,某些格子不能放,求使它们不能互相攻击的方 ...
- css3实现炫酷的文字效果_空心/立体/发光/彩色/浮雕/纹理等文字特效
这篇文章主要整理一些css3实现的一些文字特效,分享给大家, 相信您看完会有不少的收货哦! 一.css3 空心文字 <style> .hollow{ -webkit-text-stroke ...
- Web前端MVC框架的意义分析
前言: Web前端开发是Web技术发展中的一个重要组成部分,在传统的前端开发中由于外界因素的影响导致其开发形式呈现出简单化的特点,即以页面为主体来展示界面中的信息.然而随着科学技术的不断进步,Web前 ...
- Xenon's Attack on the Gangs,题解
题目: 题意: 有一个n个节点的树,边权为0-n-2,定义mex(a,b)表示除了ab路径上的自然数以外的最小的自然数,求如何分配边权使得所有的mex(a,b)之和最大. 分析: 看似有点乱,我们先不 ...
- LeetCode 哈希表 380. 常数时间插入、删除和获取随机元素(设计数据结构 List HashMap底层 时间复杂度)
比起之前那些问计数哈希表的题目,这道题好像更接近哈希表的底层机制. java中hashmap的实现是通过List<Node>,即链表的list,如果链表过长则换为红黑树,如果容量不足(装填 ...
- ATM + 购物车项目
''' 存放配置文件 ''' import os #获取项目根目录 BASE_PATH=os.path.dirname(os.path.dirname(__file__)) #获取用户目录 USER_ ...
- [JAVA]移位运算(左移<<,右移>>和无符号右移>>>)
一.背景知识 整数在内存中是以二进制的形式存在的,而且存的是该整数的补码.最高位代表符号位,正数为0,负数为1 正数的补码是其二进制本身,负数的补码则是 符号位保持1不变,其他位按位取反再加1,+0和 ...
- springbean 生命周期
springbean 和java对象得区别: 1.对象:任何符合java语法规则实例化出来的对象 2.springbean: 是spring对普通对象进行了封装为BeanDefinition,bean ...
- 开发者必备——API设计问题
本文主要探讨RPC和RESTFul两种API风格的特点以及在开发中应该如何进行技术选型,同时截取了网上社区,文章一部分关于API设计的想法和观点供读者参考,取舍. 1,背景简述 API学名:应用程序接 ...
- 通过Windows Visual Studio远程调试WSL2中的.NET Core Linux应用程序
最近两天在Linux中调试.NET Core应用程序,同时我发现在Linux中调试.NET Core应用程序并不容易.一直习惯在Visual Studio中进行编码和调试.现在我想的是可以简单快速的测 ...