zoukankan      html  css  js  c++  java
  • 5813. 【NOIP提高A组模拟2018.8.14】 计算

    ###Description
    这里写图片描述

    ###Input
    一行由空格隔开的两个整数,分别是 n 和 m。

    ###Output
    一行表示答案。

    ###Sample Input
    Input1:
    6 1
    Input2:
    6 3

    ###Sample Output
    Output1:
    10
    Output2:
    2248

    ###Data Constraint
    这里写图片描述

    ###Hint
    第一个样例中,合法的方案有 (1, 1),(1, 2),(1, 3),(1, 6),(2, 1),(2, 2),(2, 3),(3, 1),(3, 2),(6, 1) 共 10 种。

    ###题解
    一看题,艾玛,一道神仙题。心凉了一大截。

    还是无脑地上暴力吧。最后爆0。往事不堪回首
    咳咳,直接讲正解。
    题意:要求找出m*2个数的集合满足集合中的每个数可以整除n且集合中每个数的乘积小于n^m的方案。
    然后,直接求不好求。
    我们发掘一下一些神奇的性质。
    我们设
    A表示集合小于n^m的方案
    B表示集合等于n^m的方案
    C表示集合大于n^m的方案

    那么对于一个{x 1,x 2,x 3,……,x m2}令乘积小于n^m
    那么就把这个集合反一下:
    {n/x 1,n/x 2,n/x 3,……,n/x m
    2}
    那么它的乘积大于n^m

    于是可以发现,一个集合乘积小于nm,必然对应一个集合乘积大于nm
    那么,显而易见地发现:A=C
    因为,A+B+C=yueshuhe(n)^(2m)
    那么,A=(yueshuhe(n)^(2m)-B)/2

    这条式子比较优美了。
    那么我们就可以求满足集合乘积=n^m的方案就得到答案。

    我们分解n=p[i]^q[i]
    那么对于每个数的质因数中,他们的和等于q[i]*m
    这就是一个背包问题嘛。
    先枚举当前到第l个质因数
    设f[i,j]表示当前到集合中的第i个数,它分解质因数中质因数为第l个的指数的和为j的方案数。
    直接转移即可。

    顺利解决问题。
    ###代码

    uses math;
    var
            i,j,k,l,n,m,u,x,y:longint;
            ans,ano,mo:int64;
            a:array[1..10000,1..6] of longint;
            bz:array[1..1000000] of boolean;
            p,q,op:array[0..100000] of longint;
            now:array[1..6] of longint;
            f:array[0..10000,0..3000] of int64;
    function ksm(a,b:int64):int64;
    var
            t,y:int64;
    begin
            t:=1;
            y:=a;
            while b<>0 do
            begin
                    if(b and 1)=1 then
                            t:=(t*y) mod mo;
                    y:=(y*y) mod mo;
                    b:=b shr 1;
            end;
            exit(t);
    end;
    begin
            assign(input,'count.in');reset(input);
            assign(output,'count.out');rewrite(output);
            mo:=998244353;
            readln(n,m);
            for i:=2 to 1000000 do
            begin
                    if not bz[i] then
                    begin
                            inc(op[0]);
                            op[op[0]]:=i;
                            for j:=2 to 1000000 div i do
                            begin
                                    bz[j*i]:=true;
                            end;
                    end;
            end;
            u:=n;
            for i:=1 to op[0] do
            begin
                    if op[i]>u then
                    begin
                            break;
                    end;
                    if u mod op[i]=0 then
                    begin
                            inc(p[0]);
                            p[p[0]]:=op[i];
                            q[p[0]]:=1;
                            u:=u div op[i];
                    end;
                    while u mod op[i]=0 do
                    begin
                            inc(q[p[0]]);
                            u:=u div op[i];
                    end;
            end;
            for i:=1 to p[0] do q[i]:=q[i]*m;
            ans:=1;
            for l:=1 to p[0] do
            begin
            fillchar(f,sizeof(f),0);
            f[0,0]:=1;
            for i:=1 to 2*m do
            begin
                    for j:=0 to q[l] do
                    begin
                            for k:=0 to min(j,q[l] div m) do
                            begin
                                    f[i,j]:=(f[i,j]+f[i-1,j-k]) mod mo;
                            end;
                    end;
            end;
            ans:=(ans*f[2*m,q[l]]) mod mo;
            end;
            ano:=0;
            for i:=1 to trunc(sqrt(n)) do
            begin
                    if n mod i=0 then
                    begin
                            ano:=ano+1;
                            if sqr(i)<n then ano:=ano+1;
                    end;
                    //ano:=(ano*((ksm(p[i],q[i]+1)-1)*ksm(p[i]-1,mo-2)) mod mo) mod mo;
            end;
            ans:=ans+ksm(ano,2*m);
            writeln((ans*ksm(2,mo-2)) mod mo);
    end.
    
    我活在这夜里。无论周围多么黑暗,我都要努力发光!我相信着,终有一天,我会在这深邃的夜里,造就一道最美的彩虹。
  • 相关阅读:
    linux一些常用命令
    imageMagick
    nginx安装配置
    数据库操作(六)、Date函数
    数据库操作(五)、聚合函数,分组
    JQuery(一)
    数据库小结(二)
    数据库操作(四)、标量函数
    数据库操作(三)
    C#基础(六)
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11148397.html
Copyright © 2011-2022 走看看