【CJ Cup】分解

【题面链接】

首先我们知道11,13这两个因子对分解数无影响
对于这道题,我们可以从

另有 10%的数据,D 只含有 2 个素因子。

这个数据点思考
如果这两个质因子是2,3那么我们可以很轻易地写出DP方程

  • 设f[c][i][j]表示只使用前c个只由2,3组成的数并有i个2,j个3供使用–的分解方案数(代码实现上可省略第一维)
  • w[c][0],w[c][1]分别表示前c个只由2,3组成的数使用的2,3个数
    f[i][j] = f[i][j]+f[i-w[c][0]][j-w[c][1]];

如果还有因子5,7那么如果我们继续增加维数则会TLE or MLE
那么我们怎么办呢?
考虑到5只能与2,3组合,7只能与2组合,那么我们可以先算出只用因子2,3的方案数,最后用组合数学统计答案。

  • code
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 8005, mod = (int)1e9 + 9;
long long f[maxn][maxn];

int n, s[2505], d[2505], a[6];
void factor()
{
      int p[6] = {2, 3, 5, 7, 11, 13};
        memcpy(s, d, sizeof(s));
        for(int i = 0; i < 4; ++i) {
            memcpy(d, s, sizeof(d));
            do {
                a[i]++;
              for(int j = 1; j <= n; ++j) {
                d[j + 1] += (d[j] % p[i]) * 10;
                  d[j] /= p[i];
              }
            }while(!d[n + 1]);
            a[i]--;
        }   
}

const int w[8][2] = {
    1, 0, 0, 1, 2, 0, 1, 1, 3, 0,   0, 2,   2, 1,   4, 0
};

int main()
{
      freopen("factor.in", "r", stdin);
      freopen("factor.out", "w", stdout);
      char c;
      do {
        c = getchar();
      }while(c < '0' || c > '9');
      do {
        d[++n] = c - 48;
        c = getchar();
      }while('0' <= c && c <= '9');
      factor();
      f[0][0] = 1;
        for(int c = 0; c < 8; ++c) {
          for(int i = 0; i <= a[0]; ++i)
              for(int j = 0; j <= a[1]; ++j)
                    if(i >= w[c][0] && j >= w[c][1])
                      f[i][j] = (f[i][j] + f[i - w[c][0]][j - w[c][1]]) % mod;
        }
      long long ans = 0;int cnt = 0;
        for(int i = 0; i <= a[0]; ++i)
            for(int j = 0; j <= a[1]; ++j)
              if(i + j <= a[2] + a[3] && j <= a[2]) {
                    long long w = min(a[2] - j, i) - max(0, i - a[3]) + 1ll;
                    (ans += w * f[a[0] - i][a[1] - j]) %= mod;
                }
        printf("%lld", ans);
      return 0;
}

代码格式伪了,请见谅

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值