CF 300C - Beautiful Numbers [组合数求模]

2024-03-20 03:18

本文主要是介绍CF 300C - Beautiful Numbers [组合数求模],希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


数学是硬伤。

分析题目后知道就是求sigma(C[i,n]%mod)

1 ≤ n ≤ 106


下面有两种方法,

一、预处理出阶乘,直接根据组合数公式 C[i,n] = n!/( i!*(n-i)! ),由于涉及到除法取模,所以要求下逆元。

62ms.

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
inline int Rint() { int x; scanf("%d", &x); return x; }
inline int max(int x, int y) { return (x>y)? x: y; }
inline int min(int x, int y) { return (x<y)? x: y; }
#define FOR(i, a, b) for(int i=(a); i<=(b); i++)
#define FORD(i,a,b) for(int i=(a);i>=(b);i--)
#define REP(x) for(int i=0; i<(x); i++)
typedef long long int64;
#define INF (1<<30)
const double eps = 1e-8;
#define bug(s) cout<<#s<<"="<<s<<" "// a,b,n
// 1 ≤ a < b ≤ 9, 1 ≤ n ≤ 10^6
#define MAXN 1000000
#define MOD 1000000007int a, b;
int64 fact[MAXN+2];int isgood(int x) {for(; x; x/=10) {if(x%10 != a && x%10 != b) {return 0;}}return 1;
}
void calc_fact() {fact[0] = 1;FOR(i, 1, MAXN) {fact[i] = fact[i-1]*i%MOD;}
}void ext_gcd(int64 a, int64 b, int64& d, int64& x, int64& y)
{if(!b) { d = a; x = 1; y = 0; }else { ext_gcd(b, a%b, d, y, x); y-=x*(a/b); }
}int64 inv_mod(int64 a)	// ix=1(mod n)
{int64 x, y, d;ext_gcd(a, MOD, d, x, y);while(x<0) { x+=MOD; }return x;
}int64 C(int k, int n) {return fact[n]*inv_mod(fact[k]*fact[n-k])%MOD;
}int main() {a = Rint();b = Rint();int n = Rint();calc_fact();int64 ans = 0;FOR(i, 0, n) {if(isgood(a*i+b*(n-i))) {ans = (ans + C(i,n))%MOD;}}printf("%lld\n", ans);
}


二、根据递推公式 c[i]=c[i-1]*(n-i+1)/i ,先递推出所有C[n, i],因为这题n不会变,所以可以这样。同样要为 i 求逆元。

531ms

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
inline int Rint() { int x; scanf("%d", &x); return x; }
inline int max(int x, int y) { return (x>y)? x: y; }
inline int min(int x, int y) { return (x<y)? x: y; }
#define FOR(i, a, b) for(int i=(a); i<=(b); i++)
#define FORD(i,a,b) for(int i=(a);i>=(b);i--)
#define REP(x) for(int i=0; i<(x); i++)
typedef long long int64;
#define INF (1<<30)
const double eps = 1e-8;
#define bug(s) cout<<#s<<"="<<s<<" "// a,b,n
// 1 ≤ a < b ≤ 9, 1 ≤ n ≤ 10^6
#define MAXN 1000000
#define MOD 1000000007int a, b;int isgood(int x) {for(; x; x/=10) {if(x%10 != a && x%10 != b) {return 0;}}return 1;
}void ext_gcd(int64 a, int64 b, int64& d, int64& x, int64& y)
{if(!b) { d = a; x = 1; y = 0; }else { ext_gcd(b, a%b, d, y, x); y-=x*(a/b); }
}int64 inv_mod(int64 a)	// ix=1(mod n)
{int64 x, y, d;ext_gcd(a, MOD, d, x, y);while(x<0) { x+=MOD; }return x;
}// int64 C(int k, int n) {
// 	return fact[n]*inv_mod(fact[k]*fact[n-k])%MOD;
// }// #define MAXN 10000002
int64 c[MAXN+2];int64 C(int64 n, int64 k)		//C n k			
{c[0] = 1;for(int64 i=1; i<=k; i++){c[i] = c[i-1]*(n-i+1)%MOD*inv_mod(i) % MOD;}return c[k];
}int main() {a = Rint();b = Rint();int n = Rint();// calc_fact();C(n, n);int64 ans = 0;FOR(i, 0, n) {if(isgood(a*i+b*(n-i))) {ans = (ans + c[i])%MOD;}}printf("%lld\n", ans);
}


另,感觉我的求逆元的代码是不是挫了点,好像以前写组合数学的题跑的时间都比别人久。。

数学推理现在完全记不起来了。。还有什么Lucas也不会。。T-T

这篇关于CF 300C - Beautiful Numbers [组合数求模]的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/828119

相关文章

hdu4869(逆元+求组合数)

//输入n,m,n表示翻牌的次数,m表示牌的数目,求经过n次操作后共有几种状态#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#includ

cf 164 C 费用流

给你n个任务,k个机器,n个任务的起始时间,持续时间,完成任务的获利 每个机器可以完成任何一项任务,但是同一时刻只能完成一项任务,一旦某台机器在完成某项任务时,直到任务结束,这台机器都不能去做其他任务 最后问你当获利最大时,应该安排那些机器工作,即输出方案 具体建图方法: 新建源汇S T‘ 对任务按照起始时间s按升序排序 拆点: u 向 u'连一条边 容量为 1 费用为 -c,

CF 508C

点击打开链接 import java.util.Arrays;import java.util.Scanner;public class Main {public static void main(String [] args){new Solve().run() ;} }class Solve{int bit[] = new int[608] ;int l

计蒜客 Half-consecutive Numbers 暴力打表找规律

The numbers 11, 33, 66, 1010, 1515, 2121, 2828, 3636, 4545 and t_i=\frac{1}{2}i(i+1)t​i​​=​2​​1​​i(i+1), are called half-consecutive. For given NN, find the smallest rr which is no smaller than NN

Go组合

摘要 golang并非完全面向对象的程序语言,为了实现面向对象的继承这一神奇的功能,golang允许struct间使用匿名引入的方式实现对象属性方法的组合 组合使用注意项 使用匿名引入的方式来组合其他struct 默认优先调用外层方法 可以指定匿名struct以调用内层方法 代码 package mainimport ("fmt")type People struct{}type Pe

组合c(m,n)的计算方法

问题:求解组合数C(n,m),即从n个相同物品中取出m个的方案数,由于结果可能非常大,对结果模10007即可。       共四种方案。ps:注意使用限制。 方案1: 暴力求解,C(n,m)=n*(n-1)*...*(n-m+1)/m!,n<=15 ; int Combination(int n, int m) { const int M = 10007; int

代码随想录训练营day37|52. 携带研究材料,518.零钱兑换II,377. 组合总和 Ⅳ,70. 爬楼梯

52. 携带研究材料 这是一个完全背包问题,就是每个物品可以无限放。 在一维滚动数组的时候规定了遍历顺序是要从后往前的,就是因为不能多次放物体。 所以这里能多次放物体只需要把遍历顺序改改就好了 # include<iostream># include<vector>using namespace std;int main(){int n,m;cin>>n>>m;std::vector<i

INDEX+SMALL+IF+ROW函数组合使用解…

很多人在Excel中用函数公式做查询的时候,都必然会遇到的一个大问题,那就是一对多的查找/查询公式应该怎么写?大多数人都是从VLOOKUP、INDEX+MATCH中入门的,纵然你把全部的多条件查找方法都学会了而且运用娴熟,如VLOOKUP和&、SUMPRODUCT、LOOKUP(1,0/....,但仍然只能对这种一对多的查询望洋兴叹。   这里讲的INDEX+SMALL+IF+ROW的函数组合,

代码随想录算法训练营Day37|完全背包问题、518.零钱兑换II、377. 组合总和 Ⅳ、70. 爬楼梯(进阶版)

完全背包问题                  和01背包最大区别就是一个物品可以重复放多次,因此遍历空间时可以从前往后。 import java.util.*;public class Main{public static void main (String[] args) {Scanner sc = new Scanner(System.in);int m = sc.nextInt

【内网】ICMP出网ew+pingtunnel组合建立socks5隧道

❤️博客主页: iknow181 🔥系列专栏: 网络安全、 Python、JavaSE、JavaWeb、CCNP 🎉欢迎大家点赞👍收藏⭐评论✍ 通过环境搭建,满足以下条件: 攻击机模拟公网vps地址,WEB边界服务器(Windows Server 2008)模拟公司对外提供Web服务的机器,该机器可以通内网,同时向公网提供服务。内网同网段存在一台Windows内网服务