GDOI2013 整数分拆
2016-04-04 16:32
246 查看
题目描述
题目要求求一个正整数nn的分拆成kk个数的方案。其中要求满足。1、a1+a2+...+ak=n1、a_1+a_2+...+a_k=n
2、a1∗b1≤a22、a_1*b_1\leq a_2
3、a2∗b2≤a33、a_2*b_2\leq a_3
…
k、ak−1∗bk−1≤akk、a_{k-1}*b_{k-1}\leq a_k
其中bb会读入。
n≤105n\leq 10 ^5,k≤10k \leq 10,bi≤1000b_i \leq 1000.
解题思路
我们可以把原式改写:a1=a1a_1=a_1
a2=a1∗b1+x1a_2=a_1*b_1+x_1
a3=a2∗b2+x2=a1∗b1∗b2+x1∗b2+x2a_3=a_2*b_2+x_2=a_1*b_1*b_2+x_1*b_2+x_2
…
a1+a2+...+ak=na_1+a_2+...+a_k=n.
这样我把前面的kk个等式带入最后的等式,就得到了一个只含有a1a_1和xix_i的方程,其中a1≥1a_1 \geq 1.求方程的解的个数就行了。
设fi,jf_{i,j}表示前ii个未知数前ii项的和为jj的方案数。这样可以O(1)O(1)转移,总时间O(nk)O(nk).
参考代码
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define fo(i,a,b) for(int i=a;i<=b;i++) #define fd(i,a,b) for(int i=a;i>=b;i--) #define maxn 100005 #define maxk 15 #define mo 1000000007 #define mem(a,b) memset(a,b,sizeof(a)) #define ll long long using namespace std; int b[maxk],s[maxk]; int T,n,k; int f[maxk][maxn]; ll x[maxk]; int main(){ scanf("%d",&T); while (T--) { scanf("%d%d",&n,&k); fo(i,1,k-1) scanf("%d",&b[i]); s[0]=1; bool ok=0; fo(i,1,k-1) { s[i]=s[i-1]*b[i]; if (s[i]>n) { ok=1; break; } } if (ok) { puts("0"); continue; } mem(f,0); fo(i,0,k-1) { x[i]=1; fo(j,i+1,k-1) { x[i]+=s[j]/s[i]; if (x[i]>n) { x[i]=n+1; break; } } } fo(i,1,n / x[0]) f[0][i*x[0]]=1; fo(i,1,k-1) { fo(j,0,n) f[i][j]=f[i-1][j]; fo(j,x[i],n) f[i][j]=(f[i][j]+f[i][j-x[i]]) % mo; } printf("%d\n",f[k-1] ); } return 0; }
相关文章推荐
- 操作系统与c语言
- Hdu 2104 hide handkerchief
- hdoj 1437 天气情况 【概率dp】
- nginx日志管理
- AutoCAD 2016 制图软件
- bzoj 1030: [JSOI2007]文本生成器
- hdoj 1426 Sudoku Killer【数独】
- 关于View的ScrollTo, getScrollX 和 getScrollY
- HDU 4334 Trouble (暴力)
- hdoj 1434 幸福列车 【优先队列】
- Buy Tickets
- hdoj 5656 CA Loves GCD 【dp】
- Hive分析窗口函数之SUM,AVG,MIN和MAX
- 如何删除github中的repository
- 基础知识之内存管理基础
- CUDA,day-9,大规模矩阵乘法
- 第二章 JavaScript数据类型,常量与变量
- hdoj 1432 Lining Up 【思维】
- hdoj 1428 漫步校园 【dp + 最短路】
- 为什么mabatis的配置sqlMapConfigxml文件中文注释报错