5813. 【NOIP提高A组模拟2018.8.14】 计算 (结论+背包)

本文介绍了一种利用质因数分解解决特定组合计数问题的方法,通过将问题分解到每个质因数上独立解决,再综合所有质因数的结果来得到最终答案。该方法适用于寻找满足特定条件的整数数组的数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

descripition

这里写图片描述

Data Constraint

这里写图片描述

想法

  • 这题一看很神仙,只会暴搜
  • xi[1..2m],xiZ+,xi|n假设现在的数组x满足i∀[1..2m],xi∈Z+,xi|n
  • f(x)=2mi=1xi<nm然后就是找结论,如果集合f(x)=∏i=12mxi<nm
    -f(x)==2mi=1n/xi>nm那么集合f(x′)==∏i=12mn/xi>nm
  • f(x)×f(x)=n2m显然,f(x)×f(x′)=n2m
  • s12mi=1xi<nms22mi=1xi=nm所以现在令s1为∏i=12mxi<nm的方案数,s2为∏i=12mxi=nm
  • s32mi=1xi>nms3=s1s3为∏i=12mxi>nm的方案数,显然s3=s1
  • =s1+s2=(s1+s2+s3+s2)÷2答案=s1+s2=(s1+s2+s3+s2)÷2
  • s1+s2+s3,(n)2ms1+s2+s3很好求,就是(n的约数个数)2m
  • s2考虑求s2
  • n对n质因数分解,可以发现对于每个质数都是相互独立的
  • wnpajxjp设w为n中质数p的质数,aj表示xj中p的指数
  • 2mi=1aj=wm,i[1..2m],aiw所以∑i=12maj=w∗m,i∀[1..2m],ai≤w
  • f[i][j]iaisumj设f[i][j]为做到第i个数,ai的sum为j的方案数
  • 简单背包即可
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#define ll long long
#define fo(i,a,b) for(i=a;i<=b;i++) 
using namespace std;
const ll maxM=210,maxK=32,maxS=11,mo=998244353;
ll ans1,n,m,z,ss0,i,sum,ans2,f[maxM][maxK*maxM],
s[maxS][2],l,j,k;
ll ksm(ll x,ll y){
    ll k=1,z=x%mo;
    while (y){
        if (y&1) k=(k*z)%mo;
        y>>=1,z=(z*z)%mo;
    }
    return k;
}
int main(){
    freopen("a.in","r",stdin);
//  freopen("count.out","w",stdout);
    scanf("%lld%lld",&n,&m);
    z=floor(sqrt(n));
    fo(i,2,n){
        if (n%i==0){
            s[++ss0][0]=i;
            while (n%i==0){
                n/=i,s[ss0][1]++;
            }
        }
        if (n==1) break;
    }
    sum=1;
    fo(i,1,ss0)
        sum=(sum*(s[i][1]+1))%mo;
    ans1=ksm(sum,2*m);
    ans2=1;
    fo(i,1,ss0){
        memset(f,0,sizeof(f));
        f[0][0]=1;
        fo(j,0,2*m-1){
            fo(k,0,m*s[i][1])
                if (f[j][k]){
                    fo(l,0,s[i][1])
                        f[j+1][k+l]=(f[j+1][k+l]+f[j][k])%mo;
                }
        }
        ans2=(ans2*f[2*m][m*s[i][1]])%mo;
    }
    ans1=(ans1+ans2)%mo;
    ans2=ksm(2,mo-2);
    ans1=(ans1*ans2)%mo;
    printf("%lld\n",ans1);

} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值