标签:
题意:
定义f(x) 为数x的所有数字的乘积.
求满足f(k)=f(x)的不同的不含数字1的k的个数.
x的长度小于50.
不超过1000组数据.
Solution:
由于函数是乘积的形式,可以由质因子着手分析:
数字的范围是1~9,1~9中只有2,3,5,7 四个质数,即f(x)可以表示为这四个质数的幂的乘积的形式.
注意到x的长度小于50,那么质因子最多不超过150(50个8),这个时候似乎可以通过枚举4 6 8 9这四个因子的个数来,得到答案.因为5,7可以单独处理,2和3的个数可以通过4,6,8,9的个数求得.另外4的个数不超过75.而6,8,9的个数也不超过50.从时间复杂度上看是我们能够接受的.但是数据有1000组.这似乎迫使我们采用能够预处理一些我们需要的东西的算法.
令f[k][i][j],为长度为k,含有i个2因子,j个3因子的数的个数.
对于f[k+1],不过是在k的后面加了2~9这8个数,只要对每个数,更新对应的i,j就行了.
这样我们可以先预处理足够大多的f[k][i][j],因为最多不过150个2因子,100个3因子,所以预处理到f[150][150][100]就够了.
对于一组输入,统计2,3,5,7这四个因子的个数,利用多重排列的公式计算出答案,因为要对除法取模,所以要用到逆元.
#include <iostream> #include <cstdio> #include <cstring> #define LL long long using namespace std; const int MOD = 1000000007; int n, m; LL dp[160][160][160], f[200]; int sum[5]; char s[100]; LL Quikpower (LL Base, LL Power) { LL k = 1; while ( Power > 0) { if (Power & 1) k = (k * Base) % MOD; Base = (Base * Base) % MOD; Power >>= 1; } return k; } LL cnt (LL k, int m, int a, int b) { LL ans = k; for (int i = 1; i <= a + b; i++) ans = ans * (m + i) % MOD; ans = ans * Quikpower (f[a], MOD - 2) % MOD; ans = ans * Quikpower (f[b], MOD - 2) % MOD; return ans; } int main() { f[0] = 1; for (int i = 1; i <= 150; i++) f[i] = (f[i - 1] * i) % MOD; dp[0][0][0] = 1; for (int i = 0; i <= 150; i++) for (int s2 = 0; s2 <= 150; s2++) for (int s3 = 0; s3 <= 150; s3++) { if (dp[i][s2][s3] == 0) continue; dp[i + 1][s2 + 1][s3] = (dp[i + 1][s2 + 1][s3] + dp[i][s2][s3]) % MOD;//2 dp[i + 1][s2][s3 + 1] = (dp[i + 1][s2][s3 + 1] + dp[i][s2][s3]) % MOD; //3 dp[i + 1][s2 + 2][s3] = (dp[i + 1][s2 + 2][s3] + dp[i][s2][s3]) % MOD;//4 dp[i + 1][s2 + 1][s3 + 1] = (dp[i + 1][s2 + 1][s3 + 1] + dp[i][s2][s3]) % MOD; //6 dp[i + 1][s2 + 3][s3] = (dp[i + 1][s2 + 3][s3] + dp[i][s2][s3]) % MOD;//8 dp[i + 1][s2][s3 + 2] = (dp[i + 1][s2][s3 + 2] + dp[i][s2][s3]) % MOD; //9 } while (scanf ("%d", &n) != EOF) { scanf ("%s", s); memset (sum, 0, sizeof sum); for (int i = 0; i < n; i++) { int k = s[i] - ‘0‘; if (k == 2 || k == 6 || k == 8) sum[0]++; if (k == 4 || k == 8) sum[0] += 2; if (k == 3 || k == 6) sum[1]++; if (k == 9) sum[1] += 2; if (k == 5) sum[2]++; if (k == 7) sum[3]++; } int m = sum[0] + sum[1]; LL ans = 0; if (m + sum[2] + sum[3] != 0) for (int i = 0; i <= m; i++) if (dp[i][sum[0]][sum[1]]) ans = (ans + cnt (dp[i][sum[0]][sum[1]], i, sum[2], sum[3]) ) % MOD; cout << ans << endl; } }
标签:
原文地址:http://www.cnblogs.com/keam37/p/4448477.html