P6669 [清华集训2016] 组合数问题

题意:

给你n,m,k,问有多少对(i,j)满足K∣CijK|C_{i}^{j}K∣Cij​
(Cij是k的倍数C_{i}^{j}是k的倍数Cij​是k的倍数)
n,m<=1e18

题解:

n和m非常大,非常非常大,很容易想到用卢卡斯来化简
Cnmmodp=Cn/pm/p∗Cn%pm%pC_{n}^{m}\bmod p=C_{n/p}^{m/p}*C_{n\%p}^{m\%p}Cnm​modp=Cn/pm/p​∗Cn%pm%p​

对于i%p的范围就会很小,但是i/p的范围有可能还是很大,所以将Ci/pj/pC_{i/p}^{j/p}Ci/pj/p​继续用卢卡斯化简。

这样一直操作,n/p,取n%p,然后再n/p…,这不就相当于是将n转化成p进制吗?可以好好思考一下
最后式子变成:Cnmmodp=∏i=0kCnimiC_{n}^{m}\bmod p=\prod_{i=0}^{k}C_{n_{i}}^{m_{i}}Cnm​modp=∏i=0k​Cni​mi​​
n=nk∗pk+nk−1∗pk−1+...+n0n=n_{k}*p^{k}+n_{k-1}*p^{k-1}+...+n_{0}n=nk​∗pk+nk−1​∗pk−1+...+n0​
m同理

如果CnmC_{n}^{m}Cnm​是k的倍数,说明CnmmodpC_{n}^{m}\bmod pCnm​modp等于0,也就是那个累乘为0,就说明存在某一项Cnimi=0C_{ni}^{mi}=0Cnimi​=0

现在我们开始考虑CnimiC_{ni}^{mi}Cnimi​的情况,如何求其数量,我们可以先求出所有组合数C的情况,然后减去C非0的情况,那么剩下的就是C为0的情况
所有组合数C的情况就是(m+1)∗(m+2)/2+(n−m)∗(m+1)(m+1)*(m+2)/2+(n-m)*(m+1)(m+1)∗(m+2)/2+(n−m)∗(m+1),这个很好推,写出式子就有了

那C非0的情况如何求?
用数位dp来做,设dp[i][j][k]:表示考虑第i位,j和k为0或1,j为1表示第i-1位n已经取上界(本位取值存在限制),k为1表示第i-1位m取上界。为0则表示未取上界(本位取值无限制)
当第i位n不取上届时,第i位之后的每一位就可以随便取,一定会小于(数位dp思想)
详细看代码

代码:

// Problem: P6669 [清华集训2016] 组合数问题
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P6669
// Memory Limit: 500 MB
// Time Limit: 1000 ms
// Data:2021-08-27 14:38:38
// By Jozky#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
void read(){};
template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar)
{x= 0;char c= getchar();bool flag= 0;while (c < '0' || c > '9')flag|= (c == '-'), c= getchar();while (c >= '0' && c <= '9')x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();if (flag)x= -x;read(Ar...);
}
template <typename T> inline void write(T x)
{if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0');
}
void rd_test()
{#ifdef LOCALstartTime= clock();freopen("in.txt", "r", stdin);
#endif
}
void Time_test()
{#ifdef LOCALendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
int t, k;
const ll mod= 1e9 + 7;
const int maxn= 2000;
int b[maxn];
int c[maxn];
int cnt1= 0;
int cnt2= 0;
int f[maxn][2][2];
ll Sum(ll a, ll b)
{ll ans= 0;while (b) {if (b & 1)ans= (ans + a) % mod;a= (a + a) % mod;b>>= 1;}return ans % mod;
}
ll poww(ll a, ll b)
{ll ans= 1ll;while (b) {if (b & 1)ans= Sum(ans, a) % mod;a= Sum(a, a) % mod;b>>= 1;}return ans % mod;
}
ll solve(int len, int nup, int mup) //数位dp
{if (!len)return 1;if (f[len][nup][mup] != -1)return f[len][nup][mup] % mod;ll ans= 0;int l, r;//如果上一位到了上界,本位取值范围是0到b[len]//如果上一位没有到上界,本位就可以随便取值,范围是0到k-1l= nup ? b[len] : k - 1;r= mup ? c[len] : k - 1;for (int i= 0; i <= l; i++) {for (int j= 0; j <= i && j <= r; j++) {ans= (ans + solve(len - 1, nup && (i == l), mup && (j == r))) % mod;}}return f[len][nup][mup]= ans % mod;
}
int main()
{//rd_test();read(t, k);while (t--) {ll n, m;scanf("%lld%lld", &n, &m);cnt1= 0;cnt2= 0;memset(f, -1, sizeof(f));memset(b, 0, sizeof(b));memset(c, 0, sizeof(c));m= min(n, m);ll sum= ((((((m + 1) % mod * ((m + 2) % mod)) % mod) * (poww(2ll, mod - 2) % mod)) % mod) + (((n - m) % mod) * ((m + 1) % mod)) % mod) % mod;//cout << "sum=" << sum << endl;ll P= mod;while (n) {b[++cnt1]= n % k;n/= k;}while (m) {c[++cnt2]= m % k;m/= k;}printf("%lld\n", (sum - solve(cnt1, 1, 1) + mod) % mod);}//Time_test();
}

P6669 [清华集训2016] 组合数问题相关推荐

  1. UOJ #274. 【清华集训2016】温暖会指引我们前行 [lct]

    #274. [清华集训2016]温暖会指引我们前行 题意比较巧妙 裸lct维护最大生成树 #include <iostream> #include <cstdio> #incl ...

  2. [清华集训2016]石家庄的工人阶级队伍比较坚强——三进制FWT

    题目链接: [清华集训2016]石家庄的工人阶级队伍比较坚强 题目大意:有$n=3^m$个人玩石头剪刀布,共$t$轮游戏,每轮每个人要和包括自己的所有人各进行$m$次石头剪刀布.每个人在$m$轮中的决 ...

  3. 【清华集训2016】数据交互

    [清华集训2016]数据交互 比较神的\(DDP\). 首先对于给出的一条链我们分两部分统计:\(lca\)以及其他部分. 我们设两个变量\(w_i,g_i\).一条路径的权值就是路径上所有点的\(w ...

  4. [清华集训2016]你的生命已如风中残烛——组合数学

    题目链接: [清华集训2016]你的生命已如风中残烛 题目大意:共有$m+1$张牌,其中有$n$张特殊牌,每张特殊牌有一个权值$w_{i}$表示取到这张牌能获得$w_{i}$次再抽牌的机会,保证$\s ...

  5. uoj#268. 【清华集训2016】数据交互(动态dp+堆)

    传送门 动态dp我好像还真没咋做过--通过一个上午的努力光荣的获得了所有AC的人里面的倒数rk3 首先有一个我一点也不觉得显然的定理,如果两条路径相交,那么一定有一条路径的\(LCA\)在另一条路径上 ...

  6. UOJ#272. 【清华集训2016】石家庄的工人阶级队伍比较坚强

    传送门 设运算 \(op1,op2\),一个表示三进制不进位的加法,一个表示不退位的减法 设 \(cnt1[x],cnt2[x]\) 分别表示 \(x\) 转成三进制后 \(1/2\) 的个数 那么 ...

  7. 【清华集训2016】Alice和Bob又在玩游戏

    不难的题目.因为SG性质,所以只需要对一棵树求出. 然后如果发现从上往下DP不太行,所以从下往上DP. 考虑一个点对子树的合并,考虑下一个删的点在哪一个子树,那么剩下的状态实际上就是把一个子树所有能达 ...

  8. BZOJ.4738.[清华集训2016]汽水(点分治 分数规划)

    BZOJ UOJ 记\(val_i\)是每条边的边权,\(s\)是边权和,\(t\)是经过边数,\(k\)是给定的\(k\). 在点分治的时候二分答案\(x\),设\(|\frac st-k|=x\) ...

  9. BZOJ 4734 UOJ #269 [清华集训2016]如何优雅地求和 (多项式)

    题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4734 (UOJ) http://uoj.ac/problem/269 题解 ...

最新文章

  1. android 6.0 获取手机号,头条小程序获取手机号码,回调未执行,导致无法获取手机号码...
  2. LeetCode59 Spiral Matrix II
  3. Google帮助IE浏览器实现对SVG支持
  4. 【ArcGIS Pro微课1000例】0014:两种坐标系全国1km分辨率DEM下载地址(WGS84+Albers投影)
  5. vue限制点击次数_解决vue 按钮多次点击重复提交数据问题
  6. React 相关资料
  7. 思科光传输功率查询_常见的6款40G QSFP+光模块型号介绍及应用
  8. 解决vue路由守卫报错信息
  9. 腾讯网易禁止未成年人本周六玩游戏
  10. c语言求e近似值精度在10e6,中石油2013秋季学期《C语言》补考在线适用于2014年4月...
  11. 525. Contiguous Array两位求和为1的对数
  12. js 复制图片到剪切板 和 js复制文本到剪切板
  13. php实现禁止缓存,高手莫来
  14. 广州最最最牛逼的 IT 公司全在这了!
  15. 安卓res资源混淆器
  16. 在本地机上使用VNC远程连接CentOs7
  17. centos7 搭建三主三从 redis5.0集群
  18. 多搜- 多个网站一起搜(舆情监控版)
  19. 大数据杂谈篇:认识大数据生态(个人心得分享)
  20. Android Studio开发之获取Apk相关版本信息

热门文章

  1. 美国警察开特斯拉追疑犯,时速飙到193公里,然后发现没电了...
  2. GitHub 2017 年度报告,最受欢迎的编程语言是?
  3. sklearn集合算法预测泰坦尼克号幸存者
  4. pixel android8,谷歌Pixel 2更多信息:安卓8.1
  5. 重力模型matlab代码,STK基础教程.doc
  6. c语言输入一个数存数组,//从键盘上输入若干整数,并将其存入数组中,并统计输入数据的个...
  7. linux ubuntu 开启ssh服务,开启SSH服务远程登录ubuntu
  8. python frame用法_python—dataframe用法
  9. springmvc如何使用视图解析器_SpringMVC工作原理
  10. c++的assert函数