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.
    
    我活在这夜里。无论周围多么黑暗,我都要努力发光!我相信着,终有一天,我会在这深邃的夜里,造就一道最美的彩虹。
  • 相关阅读:
    poj 2584 T-Shirt Gumbo (二分匹配)
    hdu 1757 A Simple Math Problem (乘法矩阵)
    矩阵之矩阵乘法(转载)
    poj 2239 Selecting Courses (二分匹配)
    hdu 3661 Assignments (贪心)
    hdu 1348 Wall (凸包)
    poj 2060 Taxi Cab Scheme (二分匹配)
    hdu 2202 最大三角形 (凸包)
    hdu 1577 WisKey的眼神 (数学几何)
    poj 1719 Shooting Contest (二分匹配)
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11148397.html
Copyright © 2011-2022 走看看