题意:退出本身并不麻烦,麻烦的是,退出的人需要取走相应比例(1/3)金额的资产。
假设公司此时一共有n种价值的资产,每种价值的资产数量已知,请帮助心烦意乱的XHD夫妇计算一共有多少种分割资产的方法。
假设公司此时一共有n种价值的资产,每种价值的资产数量已知,请帮助心烦意乱的XHD夫妇计算一共有多少种分割资产的方法。
现在我们引用《组合数学》上最经典的一个例题:
我们要从苹果、香蕉、橘子和梨中拿一些水果出来,要求苹果只能拿偶数个,香蕉的个数要是5的倍数,橘子最多拿4个,梨要么不拿,要么只能拿一个。问按这样的要求拿n个水果的方案数。
g(x)=(1+x^2+x^4+...)(1+x^5+x^10+..)(1+x+x^2+x^3+x^4)(1+x) 就是最终的生成函数
这个母函数让我想起了去年暑假集训,那个时候母函数搞了几天都不懂,bfs完全不会,dijkstra搞不懂就反复裸拍代码,acm入门确实很难,但是一旦入了门就能感受到其中的乐趣,学的越多,感觉自己的知识就越匮乏,也就想学的更多。正是这样的循环让我的代码能力得以提升,孜孜不倦的去追求更多的知识。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
#define MOD 1000000007
const int INF=0x3f3f3f3f;
const double eps=1e-;
#define cl(a) memset(a,0,sizeof(a))
#define ts printf("*****\n");
const int MAXN=;
int n,tt;
int c1[],c2[],m[MAXN],p[MAXN];
int main()
{
int i,j,k;
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
while(scanf("%d",&n)!=EOF)
{
if(n==) break;
int sum=;
for(i=;i<=n;i++)
{
scanf("%d%d",&p[i],&m[i]);
sum+=p[i]*m[i];
}
if(sum%!=)
{
printf("sorry\n");
continue;
}
sum/=;
cl(c1),cl(c2);
for(i=;i<=p[]*m[];i+=p[]) c1[i]=; //初始化第一个函数
for(i=;i<=n;i++) //需要乘的次数
{
for(j=;j<=sum;j++) //生成函数
{
for(k=;k<=p[i]*m[i]&&(k+j)<=sum;k+=p[i]) //相乘的函数
{
c2[k+j]+=c1[j];
}
}
for(j=;j<=sum;j++)
{
c1[j]=c2[j]%;
c2[j]=;
}
}
if(c1[sum]==)
printf("sorry\n");
else printf("%d\n",c1[sum]);
}
}