The milliard Vasya's function |
Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:32768KB |
Total submit users: 89, Accepted users: 84 |
Problem 10444 : No special judgement |
Problem description |
Vasya is the beginning mathematician. He decided to make an important contribution to the science and to become famous all over the world. But how can he do that if the most interesting facts such as Pythagor's theorem are already proved? Correct! He is to think out something his own, original. So he thought out the Theory of Vasya's Functions. Vasya's Functions (VF) are rather simple: the value of the NthVF in the point S is the number of integers from 1 to N that have the sum of digits S. You seem to be great programmers, so Vasya gave you a task to find the milliard VF value (i.e. the VF with N=1000000000) because Vasya himself won't cope with the task. Can you solve the problem? |
Input |
There will be multiple test cases. Each line of input contains one integer S (1 ≤ S ≤ 81). And the last line of 0 means the end of input which should not be processed. |
Output |
For each test case, output the milliard VF value in the point S in a line. |
Sample Input |
1 81 0 |
Sample Output |
10 1 |
Problem Source |
HNU Contest |
刚才搜了下题解 很多人使用dp 写的 我在这写一个母函数思路的解法
题意不是很好懂。。。就是给出一个S 问一个整数(范围在1-1e9)所有数字之和为S的组合数
因为在1-999999999每一位上所有的数字由0-9组成 所以就是看每一位上各个数字的组成方式
可以得到一个母函数 g(x)=(1+x+x^2+……+x^9)^9
每一项中 x的系数代表该位所要取的值 九次幂代表九位数(此时会少算一个1e9)
所以将g(x)展开之后 x的指数代表组成数字中所有数位上的和 x之前的系数代表组成该系数的组合数
所以根据这个母函数就可以简单求解 但是由于少算1e9 所以a[1]最后要加1
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#define MEM(a,x) memset(a,x,sizeof a)
#define eps 1e-8
#define MOD 10009
#define MAXN 10010
#define INF 0x7fffffff
#define ll __int64
using namespace std;
int a[90],b[90];
void init()
{
MEM(a,0);
MEM(b,0);
for(int i=0;i<=9;i++)
{
a[i]=1;
b[i]=0;
}
for(int i=2;i<=9;i++)
{
for(int j=0;j<=81;j++)
{
for(int k=0;k<=9&&(j+k<=81);k++)
{
b[j+k]+=a[j];
}
}
for(int j=0;j<=81;j++)
{
a[j]=b[j];
b[j]=0;
}
}
// for(int i=1;i<=81;i++)
// printf("%d\t",a[i]);
a[1]+=1;
}
int main()
{
// freopen("ceshi.txt","r",stdin);
init();
int n;
while(scanf("%d",&n)&&n!=0)
{
printf("%d\n",a[n]);
}
return 0;
}
高深一点,(1+t+t^2+...+t^9)^9=((1-t^10)/(1-t))^9
1/(1-t)^9=sum(C(8+k,k)t^k)
(1-t^10)^9=sum(((-1)^i)*C(9,i)t^(10*i))
所以A[s]=sum(((-1)^i)*C(9,i)*C(8+k,k)) i=0,...,s/10;i*10+k=s;
如A[2]=C(10,2)=45;A[13]=C(21,13)-C(9,1)*C(11,3)=203490-1485=202005;
注意:A[s]=A[81-s],why?所以求出A[0]到A[40]即可。同时,求出来的A[1]别忘了加1;
核心代码:
p[5]={1,-9,36,-84,126};__int64 i;
for(s[0]=n=i=1;n<41;++n)s[n]=i=i*(n+8)/n;
for(r[0]=n=1;n<41;++n)for(j=i=0;j<=n/10;++j)r[n]=i+=p[j]*s[n-j*10];
----form huicpc39