hdu 4390 Number Sequence 容斥原理

将每一个数分解质因数,得到每个质因数出现的次数(和质数本身没有关系),然后就要用到容斥原理了,

也就是将每个质数出现的次数放到n个容器中去,这里要注意下1的情况也就是某个容器里面没有放数。

这样结果=总的方案数-有一个容器没放数+有2个容器没有放数……

将m个数放入n个容器的方法数有C(n+m-1,n-1)!

代码如下:

 

 1 #include<iostream>

 2 #include<stdio.h>

 3 #include<algorithm>

 4 #include<iomanip>

 5 #include<cmath>

 6 #include<cstring>

 7 #include<vector>

 8 #define ll __int64

 9 #define pi acos(-1.0)

10 #define SIZE 1024

11 using namespace std;

12 const int mod =1000000007;

13 int n;

14 ll c[101][101];

15 vector<int>p;

16 void init()

17 {

18     int i,j;

19     for(i=0;i<=100;i++){

20         c[i][0]=c[i][i]=1;

21         for(j=1;j<i;j++)

22             c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;

23     }

24 }

25 ll get(int n,int m)

26 {

27     return c[n+m-1][n-1];

28 }

29 void fen(int num)

30 {

31     int i;

32     for(i=2;i*i<=num;i++){

33         while(num%i==0){

34             p.push_back(i);

35             num/=i;

36         }

37     }

38     if(num>1) p.push_back(num);

39 }

40 ll solve()

41 {

42     int i,j,cnt,an[505]={1};

43     sort(p.begin(),p.end());

44     cnt=0;

45     for(i=1;i<p.size();i++){

46         if(p[i]!=p[i-1]) an[++cnt]=1;

47         else an[cnt]++;

48     }

49     ll ans=1;

50     for(i=0;i<=cnt;i++) ans=(ans*get(n,an[i]))%mod;

51     for(i=1;i<n;i++){

52         ll temp=c[n][i];

53         for(j=0;j<=cnt;j++){

54             temp=(temp*get(n-i,an[j]))%mod;

55         }

56         if(i&1) ans=((ans-temp)%mod+mod)%mod;

57         else ans=(ans+temp)%mod;

58     }

59     return ans%mod;

60 }

61 int main(){

62     int i,j,t;

63     init();

64     while(cin>>n&&n){

65         p.clear();

66         for(i=0;i<n;i++){

67             cin>>t;

68             fen(t);

69         }

70         printf("%I64d\n",solve());

71     }

72     return 0;

73 }
View Code

 

 

 

你可能感兴趣的:(sequence)