@topcoder - 2013TCO3A D1L3@ TrickyInequality
@description@
现有不等式组:
x_1 + x_2 + \dots + x_m \leq s\\
x_i \leq t &1 \leq i \leq n
\end{cases}
\]
求该不等式组的正整数解个数。
@accepted code@
发现这道题就 \(m - n \leq 100\) 可以利用,其他数据范围都太大了。
如果 m = n,由于还有条件 \(nt \leq s\),所以答案 = \(n^t\)。
如果 m = n + 1,假设前 n 个数之和为 p,则最后 1 个数对答案的贡献为 (s-p-1)。
可以拆成 (s-1) 与 (-p),前者实际上就是 \((s-1)\times n^t\);而后者如果考虑每一个变量的贡献为 \(-x_i\),总贡献即 \(-p\),推一下式子即可。
进一步地,不妨猜想假如前 n 个数之和为 p,则后 n - m 个数对答案的贡献是关于 p 的 n - m 次多项式。
事实上,后 n - m 个数的贡献就是 \({s - p\choose n - m}\)(比较显然)。由此也可以看出的确是关于 p 的 n - m 次多项式。
我们暴力 \(O((n - m)^2)\) 展开该多项式得到 \(\sum_{i=0}^{n-m}a_ip^i\)。
接下来如果算出 \(f_i = \sum_{1\leq x_1, x_2, \dots, x_n\leq t}(x_1 + x_2 + \dots + x_n)^i\),最后答案就是 \(ans = \sum a_if_i\)。
记 \(F(x) = \sum_{i=0}\frac{\sum_{j=1}^{t}j^i}{i!}x^i\),则 \(f_i = i!\times [x^i]F^n(x)\)。
自然数幂和(使用斯特林数即可)算出 \(F(x)\) 前 m - n 项,再快速幂算 \(F^n(x)\)。多项式乘法直接 \(O((m-n)^2)\) 算。
因此总时间复杂度 \(O((m-n)^2\log n)\)。
@accepted code@
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 105;
const int MOD = 1000000007;
inline int add(int x, int y) {return (x + y >= MOD ? x + y - MOD : x + y);}
inline int sub(int x, int y) {return (x - y < 0 ? x - y + MOD : x - y);}
inline int mul(int x, int y) {return 1LL * x * y % MOD;}
int pow_mod(int b, int p) {
int ret = 1;
for(int i=p;i;i>>=1,b=mul(b,b))
if( i & 1 ) ret = mul(ret, b);
return ret;
}
int fct[MAXN + 5], ifct[MAXN + 5], b[MAXN + 5];
void init() {
fct[0] = 1; for(int i=1;i<=MAXN;i++) fct[i] = mul(fct[i - 1], i);
ifct[MAXN] = pow_mod(fct[MAXN], MOD - 2);
for(int i=MAXN-1;i>=0;i--) ifct[i] = mul(ifct[i + 1], i + 1);
for(int i=0;i<=MAXN;i++) {
b[i] = (i == 0);
for(int j=0;j<i;j++)
b[i] = sub(b[i], mul(b[j], ifct[i-j+1]));
}
}
int sum(int n, int k) {
int ret = 0; n = add(n, 1);
for(int i=1,pw=n;i<=k+1;i++,pw=mul(pw,n))
ret = add(ret, mul(b[k-i+1], mul(pw, ifct[i])));
if( k == 0 ) ret = sub(ret, 1);
return mul(ret, fct[k]);
}
int a[MAXN + 5];
void solve(int s, int p) {
a[0] = 1;
for(int i=0;i<p;i++) {
int k = sub(s, i);
a[i + 1] = sub(0, a[i]);
for(int j=i;j>=1;j--)
a[j] = sub(mul(k, a[j]), a[j - 1]);
a[0] = mul(k, a[0]);
}
for(int i=0;i<=p;i++)
a[i] = mul(a[i], ifct[p]);
}
int t1[MAXN + 5], t2[MAXN + 5];
void mul(int *A, int *B, int p) {
for(int i=0;i<=p;i++) t1[i] = A[i], t2[i] = B[i], A[i] = 0;
for(int i=0;i<=p;i++)
for(int j=0;j<=i;j++)
A[i] = add(A[i], mul(t1[j], t2[i-j]));
}
int f[MAXN + 5], g[MAXN + 5];
void solve2(int p, ll n, int t) {
for(int i=0;i<=p;i++)
f[i] = 0, g[i] = mul(sum(t, i), ifct[i]);
f[0] = 1;
for(ll i=n;i;i>>=1,mul(g,g,p))
if( i & 1 ) mul(f, g, p);
}
class TrickyInequality{
public:
int countSolutions(ll s, int t, int n, int m) {
int p = m - n, ans = 0;
init(), solve(s % MOD, p), solve2(p, n, t);
for(int i=0;i<=p;i++)
ans = add(ans, mul(a[i], mul(f[i], fct[i])));
return ans;
}
};
@details@
另外,这题好像可以用直接容斥然后构造 k 阶差分公式做到 \(O((n-m)^2)\)(orz 栋爷)。
有空。。。再来填坑?
@topcoder - 2013TCO3A D1L3@ TrickyInequality的更多相关文章
- Topcoder SRM570 D1L3 CurvyonRails
几个样例: 5 5wCCwwwCC....w......www..wReturns: 0 3 3C.w....C.Returns: 1 21 20CC..CCCw.CwC..CC.w.CC.CCCwC ...
- @topcoder - SRM766R1 D1L3@ ShortestMissingSubsequences
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个大小为 G 的字符集,并给定一个长度为 N 的字符串 A ...
- TopCoder kawigiEdit插件配置
kawigiEdit插件可以提高 TopCoder编译,提交效率,可以管理保存每次SRM的代码. kawigiEdit下载地址:http://code.google.com/p/kawigiedit/ ...
- 记第一次TopCoder, 练习SRM 583 div2 250
今天第一次做topcoder,没有比赛,所以找的最新一期的SRM练习,做了第一道题. 题目大意是说 给一个数字字符串,任意交换两位,使数字变为最小,不能有前导0. 看到题目以后,先想到的找规律,发现要 ...
- TopCoder比赛总结表
TopCoder 250 500 ...
- Topcoder几例C++字符串应用
本文写于9月初,是利用Topcoder准备应聘时的机试环节临时补习的C++的一部分内容.签约之后,没有再进行练习,此文暂告一段落. 换句话说,就是本文太监了,一直做草稿看着别扭,删掉又觉得可惜,索性发 ...
- TopCoder
在TopCoder下载好luncher,网址:https://www.topcoder.com/community/competitive%20programming/ 选择launch web ar ...
- TopCoder SRM 596 DIV 1 250
body { font-family: Monospaced; font-size: 12pt } pre { font-family: Monospaced; font-size: 12pt } P ...
- 求拓扑排序的数量,例题 topcoder srm 654 div2 500
周赛时遇到的一道比较有意思的题目: Problem Statement There are N rooms in Maki's new house. The rooms are number ...
随机推荐
- strut2登陆注册验证码
1. 生成图片和验证码 package com.jmu.code; import java.awt.Color; import java.awt.Font; import java.awt.Graph ...
- Gym101612H Hidden Supervisors
题目链接:https://vjudge.net/problem/Gym-101612H 知识点: 贪心 解题思路: 我们称除了以 \(1\) 号结点为根的树以外的树为 “其他树”. 对于每一棵树,先自 ...
- JavaScript数组常见用法
最近做一个项目中做一个竞猜游戏界面,游戏规则和彩票是一样的.在实现“机选一注”,“机选五注”的时候遇到数组的一些操作,例如产生['01', '02' ... '35']这样的数组,随机抽取不重复的元素 ...
- Android Studio代码编译通过但是提示停止运行
这种问题也许有很多可能,但是我遇到过一种,下面分享给大家希望问题会得到解决 检查你的布局文件中图片的位置 如果图片名前有“(v24)”的删掉 重新插入图片到这个目录 然后就可以正常运行了
- Docker 入门:什么是 Docker ?
Docker 解决了软件环境部署复杂的问题. 对于一个传统的软件工程,开发人员把写好的代码放到服务器上去运行是一件很头疼的事情,因为常常会出现环境不兼容而导致各种各样的 Bug. 比如说,开发是在 w ...
- ansible模块详解
[简单介绍] Ansible是一种agentless(基于ssh),可实现批量配置.命令执行和控制,基于Python实现的自动化运维工具. 有以下两个特性: 模块化:通过调用相关模块,完成指定任务,且 ...
- String类练习
1.模拟一个trim方法,去除字符串两端的空格 2.将一个字符串进行反转.将字符串中指定部分进行反转 3.获取一个字符串在另一个字符串中出现的次数 4.获取两个字符串中最大相同子串 5.对字符串中字符 ...
- 五、Java - 集合
一.集合 Java 中的集合类存放于 java.util 包中,是一个存放对象的容器. 集合存放的是对对象的引用,对象本身还是存在于 JVM 堆内存中. 存放的是对象,即引用数据类型,对于基本数据类型 ...
- angularjs 路由切换回到顶部
angularjs路由切换 页面不会回到顶部 问题: 在angularjs中 ui-sref或者$state.go(),通过路由切换页面,发现新打开的路由页面仍然停留在上一次的路由页面访问的位置. ...
- 如何发布一个 npm 包
一 背景 在工作时,突然接到经理的一个要求,需要将一个react的高阶组件函数封装成一个npm包.之前从没弄过,当场还是有些懵逼的,但是这毕竟是工作,不能推脱.于是开始了学习.汤坑之旅.最终包发布,线 ...