• [jzoj]3760.【BJOI2014】Euler


    Link

      https://jzoj.net/senior/#main/show/3760

    Description

      欧拉函数  φ(n)  定义为不超过正整数 n 并且与 n 互素的整数的数目。
      可以证明 φ(n) =  n ∗ ∏ (1 − 1 / pi). 其中 pi(1 <= i <= k)是 n 的全部素因子。
      已知 y,求最小的自然数 x 使得 φ(x) = y.
      多组询问。

    Solution

    30分:

      可以枚举每一个x,判断所得出来的φ(x)是否等于y。可证x≤7y 

    60分:

      可能是某些神奇的算法,或者是给没有int64的人一点分

    100分:

      这里有三种解题思路

      三种都可以用搜索来做,也可以使用动态规划来做。

      动态规划公式:F[i,j]表示前i个可能的质因子,分解后得到状态S的最小x’

    (1)欧拉函数定义

      根据欧拉函数的定义,很显然可以得到如下两条性质:

      ①φ(x)=x-1......................当x是素数时

      ②φ(xy)=φ(x)*φ(y)..........对任何情况都是成立的

      于是,分别得出如下结论:

        根据①:x的质因数可能是y的约数加一,

        根据②:x的质因数可能是y的质因数。

      可能有点难理解,但的确如此。

    (2)分解欧拉函数公式

      我们可以尝试一下分解每个式子。

      x=p1q1*p2q2*...pnqk(p数组为x质因子,q数组为每个质因子的个数)

      显然如下

      φ(x)=x*(p1-1/p1)(p2-1/p2).....(pk-1/pk)..................................公式

      φ(x)=p1q1*p2q2*...pn^qn*(p1-1/p1)(p2-1/p2).....(pk-1/pk).......将x带入

      当q1=q2=....=qk=1时,剩下的,就只有(p1-1)*(p2-1)*...(pk-1)

      有某些q数组的元素大于一时,就是上面那些式子,再多乘那些消掉以后多出来的pxqx,即(p1-1)*(p2-1)*...(pk-1)*pxqx,注意,这里x只是某一个举例子的

      所以可以发现,x的质因数可能是y的约数加一,x的质因数可能是y的质因数。

    (3)分解欧拉函数公式

      同样是拆分式子,跟(2)差不多的,

      φ(x)=∏piqi * ∏(1-1/pi)

      φ(x)=∏[ piqi (1-1/pi) ]............合并连乘的

      φ(x)=∏[ piqi-1 (1-1/pi)*pi ]...拆一个pi出来与后面的式子相乘

      φ(x)=∏[ piqi-1 (pi-1) .............约分得到的

      同样可以得到上面的结论(x的质因数可能是y的约数加一,x的质因数可能是y的质因数),递归或者动态规划做就行了

    剪枝

      可以加快排,大小值,记忆化来剪枝。

    Code(2)

    uses math;
    var
            x,min:int64;
            n,t,i,j,k:longint;
            prime,bz:array[0..10000] of int64;
    procedure dg(k,x,now:int64);
    var
            s,ss:qword;
            i:longint;
    begin
            if now>min then
                    exit;
    
            if x=1 then
            begin
                    min:=now;
    
                    exit;
            end;
    
            if k>prime[0] then
                    exit;
    
            s:=1;
            for i:=0 to 40 do
            begin
                    if s>x then
                            break;
    
                    if s>x/prime[k] then
                            break;
    
                    if x mod (s*prime[k])<>0 then
                            break;
    
                    bz[k]:=i;
                    dg(k+1,x div (s*prime[k]),now*s*(prime[k]+1));
                    bz[k]:=-1;
    
                    s:=s*(prime[k]+1);
            end;
    
            dg(k+1,x,now);
    end;
    function pd(x:int64):boolean;
    var
            i:longint;
    begin
            for i:=2 to trunc(sqrt(x)) do
                    if x mod i=0 then
                            exit(false);
    
            exit(true);
    end;
    
    procedure q(l,r:longint);
    var
            t,mid:int64;
            i,j:longint;
    begin
            i:=l;
            j:=r;
            mid:=prime[(l+r) shr 1];
    
            while i<j do
            begin
                    while prime[i]>mid do inc(i);
                    while prime[j]<mid do dec(j);
    
                    if i<=j then
                    begin
                            t:=prime[i]; prime[i]:=prime[j]; prime[j]:=t;
    
                            inc(i); dec(j);
                    end;
            end;
    
            if i<r then q(i,r);
            if l<j then q(l,j);
    end;
    begin
            readln(n);
            for j:=1 to n do
            begin
                    readln(x);
    
                    fillchar(prime,sizeof(prime),0);
                    for i:=1 to trunc(sqrt(x)) do
                            if x mod i=0 then
                            begin
                                    if pd(i+1) then
                                    begin
                                            inc(prime[0]);
    
                                            prime[prime[0]]:=i;
                                    end;
    
    
                                    if x div i<>i then
                                    begin
                                            if pd(x div i+1) then
                                            begin
                                                    inc(prime[0]);
    
                                                    prime[prime[0]]:=x div i;
                                            end;
                                    end;
                            end;
    
                    q(1,prime[0]);
    
                    fillchar(bz,sizeof(bz),255);
    
                    min:=21099511627776;
                    dg(1,x,1);
                    writeln(min);
            end;
    end.
    uses math;
    const maxn=1000000;
    var
            pr,flag:array[0..10000] of int64;
            z,have:array[0..100000] of int64;
            bz:array[0..1000000] of boolean;
            n,nn,tot,ans:int64;
            i,j,p:longint;
    procedure dfs(k,sum,max:int64; flag2:boolean);
    begin
            if max*sum>=ans then exit;
            if sum=1 then
            begin
                    ans:=min(ans,max);
                    exit;
            end;
            if k>have[0]+pr[0] then exit;
    
            if k<=have[0] then
            begin
                    if (have[k]<=1) or (sum mod have[k]<>0) then dfs(k+1,sum,max,flag2) else
                    begin
                            dfs(k+1,sum div have[k],max*(have[k]+1),true);
                            dfs(k+1,sum,max,flag2);
                    end;
            end
            else
            begin
                    if flag2 then exit;
    
                    inc(flag[have[k]]);
                    if flag[have[k]]=1 then begin if sum mod (have[k]-1)=0 then dfs(k+1,sum div (have[k]-1),max*have[k],flag2); end
                            else
                    if sum mod have[k]=0 then dfs(k+1,sum div have[k],max*have[k],flag2);
                    dec(flag[have[k]]);
    
                    dfs(k+1,sum,max,flag2);
            end;
    end;
    function pd(x:int64):boolean;
    begin
            for j:=1 to z[0] do
            begin
                    if sqr(z[j])>x then exit(true);
                    if x mod z[j]=0 then exit(false);
            end;
    end;
    begin
            for i:=2 to maxn do
            begin
                    if not bz[i] then
                    begin
                            inc(z[0]);
                            z[z[0]]:=i;
                    end;
                    for j:=1 to z[0] do
                    begin
                            if z[j]*i>maxn then break;
                            bz[z[j]*i]:=true;
                            if i mod z[j]=0 then break;
                    end;
            end;
    
            readln(tot);
            for p:=1 to tot do
            begin
                    have[0]:=0;
                    pr[0]:=0;
                    readln(n);
                    for i:=trunc(sqrt(n)) downto 1 do
                            if n mod i=0 then
                            begin
                                    if pd(i+1) then begin inc(have[0]); have[have[0]]:=i; end;
                                    if i=n div i then continue;
                                    if pd(n div i+1) then begin inc(have[0]); have[have[0]]:=n div i; end;
                            end;
                    nn:=n;
                    for i:=1 to z[0] do
                    begin
                            if sqr(z[i])>nn then break;
                            if nn mod z[i]=0 then begin inc(pr[0]); have[pr[0]+have[0]]:=z[i]; end;
                            while nn mod z[i]=0 do
                            begin
                                    inc(pr[0]);
                                    have[pr[0]+have[0]]:=z[i];
                                    nn:=nn div z[i];
                            end;
                    end;
    
                    ans:=maxlongint*maxlongint;
                    dfs(1,n,1,false);
                    writeln(ans);
            end;
    end.
  • 相关阅读:
    参加“51testing第70期深圳技术沙龙”感想
    软件测试的实质
    JMeter使用技巧
    一个软件测试员的工作与学习(二)
    JMeter基础之元件的作用域与执行顺序
    测试之美测试员的心思你不懂
    博客搬家的原因与文章被转的看法
    ubuntu下配置java环境
    敏捷软件测试初见
    软件测试人员分工
  • 原文地址:https://www.cnblogs.com/philchieh/p/7118496.html
Copyright © 2020-2023  润新知