IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> AT2000 [AGC002F] Leftmost Ball(dp、组合数学) -> 正文阅读

[C++知识库]AT2000 [AGC002F] Leftmost Ball(dp、组合数学)

解析

如果之前有些卡住的题可以说是奇淫技巧的话,这道题的思路只能说太经典了。
感觉其实也就是紫的难度吧,没做出来有些可惜。
还是有写畏黑情绪,见到黑题本能的感觉做不出来。

首先是一个比较自然的题意转化:有 k-1 个 1-n 的球, k 个 0 号球,要求任意前缀 0 号球的数量不少于 1-n 的球的种类数。
然后就不会了
关键就是给每种合法方式找到一种唯一的统计方式。

首先一个常见做法是先钦定一个颜色的出现次序,最后答案乘阶乘即可。
f i , j f_{i,j} fi,j? 表示放了 i 个白球,j 种球的方案数。
然后,考虑下一个球的颜色,如果是白色,直接填上即可。如果不是白色,我们就同时确定这种颜色剩余的 k-2 个球的位置,这样以后就不用考虑了。由于这些球的位置任意,所以我们刚才的“下一个球”其实是指“下一个空位置的球”。
然后不难发现对于任意合法方案,这样的转移都会且只会统计一次。

时间复杂度 O ( n 2 ) O(n^2) O(n2)
k = 1 k=1 k=1 的时候组合数会出现 -1,直接特判即可。

代码

//luogu
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define LL __int128
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
using namespace std;

const int N=2050;
const int mod=1e9+7;
inline ll read(){
  ll x(0),f(1);char c=getchar();
  while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();}
  while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
  return x*f;
}


inline ll ksm(ll x,ll k){
  ll res(1);
  while(k){
    if(k&1) res=res*x%mod;
    x=x*x%mod;
    k>>=1;
  }
  return res;
}
int n,k;

ll jc[N*N],ni[N*N];
void init(int n){
  jc[0]=1;
  for(int i=1;i<=n;i++) jc[i]=jc[i-1]*i%mod;
  ni[n]=ksm(jc[n],mod-2);
  for(int i=n-1;i>=0;i--) ni[i]=ni[i+1]*(i+1)%mod;
  return;
}
inline ll C(int n,int m){
  return jc[n]*ni[m]%mod*ni[n-m]%mod;
}
ll f[N][N];

signed main(){
  #ifndef ONLINE_JUDGE
  freopen("a.in","r",stdin);
  freopen("a.out","w",stdout);
  #endif
  n=read();k=read();
  if(k==1){
    puts("1");return 0;
  }
  init(n*k);
  for(int i=1;i<=n;i++){
    f[i][0]=1;
    for(int j=1;j<=i;j++){
      f[i][j]=(f[i-1][j]+f[i][j-1]*C(n*k-i-(j-1)*(k-1)-1,k-2))%mod;
    }
  }
  printf("%lld\n",f[n][n]*jc[n]%mod);
  return 0;
}


  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-30 08:30:43  更:2022-04-30 08:32:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:12:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码