JZOJ5813. 【NOIP提高A组模拟2018.8.14】 计算

这里写图片描述

题解

X = ( x 1 , x 2 , . . . , x 2 m )
假设里面的 x i 都是n的约数,
设F(X)表示X里面数的乘积和。
对于的,设 X = ( n / x 1 , n / x 2 , . . . , n / x 2 m )
当F(X)< n m ,则F(X’)> n m

所以,设有s1个F(X)< n m ,s2个F(X)= n m ,s3个F(X)> n m
显然,有个刚刚的结论:s1=s3,
而且我们也知道s1+s2+s3=n的约数个数的2m次方。

于是目标就变为了求s2。
可以知道每个质因子的贡献是独立的,
于是就对于单独的一个质因子考虑它的贡献:
f i , j 表示当前在第i个位置,前面已经用掉了j个质因子的方案数。
每个位置可以不填这个质因子,但最多不能超过n中这个质因子出现的次数,
因为要是x是n的约数。
将每个质因子的贡献乘起来就是s2了。

code

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <time.h>
#define ll long long
#define N 100003
#define M 103
#define db double
#define P putchar
#define G getchar
using namespace std;
char ch;
void read(int &n)
{
    n=0;
    ch=G();
    while((ch<'0' || ch>'9') && ch!='-')ch=G();
    ll w=1;
    if(ch=='-')w=-1,ch=G();
    while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
    n*=w;
}

int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}

const int mo=998244353;
int n,m,p[N],k[N],cnt,f[203][6003],q,s,ss,t;
ll ans;

void add(int& x,int y){x=x+y>=mo?x+y-mo:x+y;}

ll ksm(ll x,int y)
{
    ll s=1;
    for(;y;y>>=1,x=x*x%mo)
        if(y&1)s=s*x%mo;
    return s;
}

int main()
{
    freopen("count.in","r",stdin);
    freopen("count.out","w",stdout);

    read(n);read(m);
    for(int i=1;i*i<=n;i++)
        if(n%i==0)
        {
            q+=2;
            if(n/i==i)q--;
        }

    s=n;ans=1;
    for(int i=2;i*i<=s;i++)
        if(s%i==0)
        {
            for(p[++cnt]=i;s%i==0;s/=i)k[cnt]++;
        }
    if(s>1)p[++cnt]=s,k[cnt]=1;

    for(int i=1;i<=cnt;i++)
    {
        memset(f,0,sizeof(f));
        f[0][0]=1;
        for(int j=1;j<=2*m;j++)
        {
            ss=min(j,m)*k[i];
            for(int s=0;s<=ss;s++)
            {
                t=min(s,k[i]);
                for(int w=0;w<=t;w++)
                    add(f[j][s],f[j-1][s-w]);
            }
        }
        ans=ans*f[2*m][m*k[i]]%mo;
    }

    ans=(ans+ksm(q,2*m))%mo*ksm(2,mo-2)%mo;
    printf("%lld",ans);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/lijf2001/article/details/81674029
今日推荐