数学:整数拆分-带约束

本文介绍了一道整数拆分问题HDU4658的解法,利用五边形数定理和母函数理论,探讨了如何在限制条件下求解整数拆分的方法。

HDU4658:使用五边形数定理和母函数进行约束整数拆分

之前的那个一个题的公式是这样的:

f[n]=∑(-1)^(k-1)*(f[n-k*(3*k-1)/2]+f[n-k*(3*k+1)/2])

其中n-k*(3*k-1)/2>=0,n-k*(3*k+1)/2>=0

加入了限制条件:拆分出来的整数中,任意整数都不能出现k次或k次以上

因此求的时候要使用公式的推导定理,母函数来求

生成函数(也有叫做“母函数”的)是说,构造这么一个多项式函数g(x),使得x的n次方系数为f(n)

1+x+x^2+...

其中的系数f[n]就是全由1组成的n有多少种

1+x^2+x^4+...

其中的系数f[n]就是全由2组成的n有多少种

把这两个式子乘起来就变成了

(1+x+x^2..;.)*(1+x^2...)=1+x+2*x^2+x^3+x^4...

其中x^2系数2表示拆分整数2的方案数

无限制的拆分就可以理解成

中x^n的系数就是所求值

这题加了k的限制,所以得到的生成函数式

G(x)=(1+x+x^2+...+x^(k-1))*(1+x^2+x^4+x^2(k-1))*...

=(1-x^k)/(1-x)*(1-x^2k)/(1-x^2)*(1-x^3k)/(1-x^3)...

令y=x^k

=∏(1-y^i)/∏(1-x^i)(1<=i<∞)

=Q(x^k)/Q(x) (根据五边形数定理得)

=Q(x^k)*P(x)

 

∏(1-x^i)形式的可用五边形数定理来求

然后用这个公式代入

=Q(x^k)*P(x)
=( 1 - x^k - (x^k)^2 + (x^k)^5 + (x^k)^7 -... ) * ( 1 + x + 2*x^2 + 3*x^3 + 5*x^4 + 7*x^5 + ... )

这里的P(x)就是无限制拆分里面的那个

它的计算方法是:

p[n]=∑(-1)^(k-1)*(p[n-k*(3*k-1)/2]+p[n-k*(3*k+1)/2])

这样只需要求(1-x^k-x^2k+x^5k+x^7k-x^12k-x^15k+x^22k+x^26k)*(1+p(1)x+p(2)x+p(3)x+...)中x^n的系数了

 1 #include<cstdio>
 2 using namespace std;
 3 const int MOD=1e9+7;
 4 int n,k;
 5 int dp[100005];
 6 void init()
 7 {
 8     dp[0]=1;
 9     for(int i=1;i<=100000;i++)
10     {
11         for(int j=1,r=1;i-(3*j*j-j)/2>=0;j++,r*=-1)
12         {
13             dp[i]+=dp[i-(3*j*j-j)/2]*r;
14             dp[i]%=MOD;
15             dp[i]=(dp[i]+MOD)%MOD;
16             if(i-(3*j*j+j)/2>=0)
17             {
18                 dp[i]+=dp[i-(3*j*j+j)/2]*r;
19                 dp[i]%=MOD;
20                 dp[i]=(dp[i]+MOD)%MOD;
21             }
22         }
23     }
24 }
25 int solve(int n,int k)
26 {
27     int ans=dp[n];
28     for(int j=1,r=-1;n-k*(3*j*j-j)/2>=0;j++,r*=-1)
29     {
30         ans+=dp[n-k*(3*j*j-j)/2]*r;
31         ans%=MOD;
32         ans=(ans+MOD)%MOD;
33         if(n-k*(3*j*j+j)/2>=0)
34         {
35             ans+=dp[n-k*(3*j*j+j)/2]*r;
36             ans%=MOD;
37             ans=(ans+MOD)%MOD;
38         }
39     }
40     return ans;
41 }
42 int main()
43 {
44     init();
45     int T;
46     scanf("%d",&T);
47     while(T--)
48     {
49         scanf("%d%d",&n,&k);
50         printf("%d\n",solve(n,k));
51     }
52     return 0;
53 }

 

转载于:https://www.cnblogs.com/aininot260/p/9492162.html

# P11362 [NOIP2024] 遗失的赋值 ## 题目描述 小 F 有 $n$ 个变量 $x_1, x_2, \ldots , x_n$。每个变量可以取 $1$ 至 $v$ 的整数取值。 小 F 在这 $n$ 个变量之间添加了 $n - 1$ 条二元限制,其中第 $i$($1 \leq i \leq n - 1$)条限制为:若 $x_i = a_i$,则要求 $x_{i+1} = b_i$,**且 $a_i$ 与 $b_i$ 为 $1$ 到 $v$ 之间的整数**;当 $x_i \neq a_i$ 时,第 $i$ 条限制对 $x_{i+1}$ 的值不做任何约束。除此之外,小 F 还添加了 $m$ 条一元限制,其中第 $j$($1 \leq j \leq m$)条限制为:$x_{c_j} = d_j$。 小 F 记住了所有 $c_j$ 和 $d_j$ 的值,但把所有 $a_i$ 和 $b_i$ 的值都忘了。同时小 F 知道:存在给每一个变量赋值的方案同时满足所有这些限制。 现在小 F 想知道,有多少种 $a_i, b_i$($1 \leq i \leq n - 1$)取值的组合,使得能够确保至少存在一种给每个变量 $x_i$ 赋值的方案可以同时满足所有限制。由于方案数可能很大,小 F 只需要你输出方案数对 $10^9 + 7$ 取模的结果。 ## 输入格式 **本题包含多组测试数据**。 输入的第一行包含一个整数 $T$,表示测试数据的组数。 接下来包含 $T$ 组数据,每组数据的格式如下: 第一行包含三个整数 $n, m, v$,分别表示变量个数、一元限制个数和变量的取值上限。 接下来 $m$ 行,第 $j$ 行包含两个整数 $c_j, d_j$,描述一个一元限制。 ## 输出格式 对于每组测试数据输出一行,包含一个整数,表示方案数对 $10^9 + 7$ 取模的结果。 ## 输入输出样例 #1 ### 输入 #1 ``` 3 2 1 2 1 1 2 2 2 1 1 2 2 2 2 2 1 1 1 2 ``` ### 输出 #1 ``` 4 3 0 ``` ## 说明/提示 **【样例 1 解释】** - 对于第一组测试数据,所有可能的 $(a_1, b_1)$ 取值的组合 $(1, 1), (1, 2), (2, 1), (2, 2)$ 都满足限制。例如,$(a_1, b_1) = (1, 1)$ 时,$(x_1, x_2) = (1, 1)$ 满足所有限制,而 $(a_1, b_1) = (2, 2)$ 时,$(x_1, x_2) = (1, 1)$ 与 $(x_1, x_2) = (1, 2)$ 均满足所有限制。 - 对于第二组测试数据,只有 $(x_1, x_2) = (1, 2)$ 一种可能的变量赋值,因此只有 $(a_1, b_1) = (1, 1)$ 不满足限制,其余三种赋值均满足限制。 - 对于第三组测试数据,不存在一种变量赋值同时满足 $x_1 = 1$ 和 $x_1 = 2$,因此也不存在满足限制的 $(a_1, b_1)$。 **【样例 2】** 见选手目录下的 `assign/assign2.in` 与 `assign/assign2.ans`。 该样例共有 $10$ 组测试数据,其中第 $i$($1 \leq i \leq 10$)组测试数据满足数据范围中描述的测试点 $i$ 的限制。 **【样例 3】** 见选手目录下的 `assign/assign3.in` 与 `assign/assign3.ans`。 该样例共有 $10$ 组测试数据,其中第 $i$($1 \leq i \leq 10$)组测试数据满足数据范围中描述的测试点 $i + 10$ 的限制。 **【数据范围】** 对于所有的测试数据,保证: - $1 \leq T \leq 10$, - $1 \leq n \leq 10^9$,$1 \leq m \leq 10^5$,$2 \leq v \leq 10^9$, - 对于任意的 $j$($1 \leq j \leq m$),都有 $1 \leq c_j \leq n$,$1 \leq d_j \leq v$。 ::cute-table{tuack} | 测试点 | $n \leq$ | $m \leq$ | $v \leq$ | 特殊性质 | | :----------: | :----------: | :----------: | :----------: | :----------: | | $1, 2$ | $6$ | $6$ | $2$ | 无 | | $3$ | $9$ | $9$ | ^ | ^ | | $4, 5$ | $12$ | $12$ | ^ | ^ | | $6$ | $10^3$ | $1$ | $10^3$ | ^ | | $7$ | $10^5$ | ^ | $10^5$ | ^ | | $8,9$ | $10^9$ | ^ | $10^9$ | ^ | | $10$ | $10^3$ | $10^3$ | $10^3$ | A | | $11$ | $10^4$ | $10^4$ | $10^4$ | ^ | | $12$ | $10^5$ | $10^5$ | $10^5$ | ^ | | $13$ | $10^4$ | $10^3$ | $10^4$ | B | | $14$ | $10^6$ | $10^4$ | $10^6$ | ^ | | $15, 16$ | $10^9$ | $10^5$ | $10^9$ | ^ | | $17$ | $10^4$ | $10^3$ | $10^4$ | 无 | | $18$ | $10^6$ | $10^4$ | $10^6$ | ^ | | $19, 20$ | $10^9$ | $10^5$ | $10^9$ | ^ | 特殊性质 A:保证 $m = n$,且对于任意的 $j$($1 \leq j \leq m$),都有 $c_j = j$。 特殊性质 B:保证 $d_j = 1$。C++代码
08-29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值