zoukankan      html  css  js  c++  java
  • 2018.08.10【2018提高组】模拟A组&省选 划分

    #Description
    有一个未知的序列x,长度为n。它的K-划分序列y指的是每连续K个数的和得到划分序列,y[1]=x[1]+x[2]+…+x[K],y[2]=x[K+1]+x[K+2]+…+x[K+K]…。若n不被K整除,则y[n/K+1]可以由少于K个数加起来。比如n=13,K=5,则y[1]=x[1]+…+x[5],y[2]=x[6]+…+x[10],y[3]=x[11]+x[12]+x[13]。若小A只确定x的K[1]划分序列以及K[2]划分序列…K[M]划分序列的值情况下,问她可以确定x多少个元素的值。

    #Input
    第一行输入两个正整数n,M。
    第二行输入M个正整数表示K[1],K[2]…K[M]。

    #Output
    输出1个整数,表示能确定的元素

    #Sample Input
    【输入样例1】
    3 1
    2
    【输入样例2】
    6 2
    2 3
    【输入样例3】
    123456789 3
    5 6 9

    #Sample Output
    【输出样例1】
    1
    【输出样例2】
    2
    【输出样例3】
    10973937

    #Data Constraint
    对于20%的数据,3 <= N <= 2000,M<=3。
    对于40%的数据,3 <= N <= 5*10^6。
    对于100%的数据,3 <= N <= 10^9 , 1 <= M <= 10,2 <= K[i] < N。

    #Hint
    【样例1解释】
    小A知道x的2-划分序列,即分别知道x[1]+x[2],x[3]的值。
    小A可以知道x[3]的值。
    【样例2解释】
    小A知道x的2-划分序列,即分别知道x[1]+x[2],x[3]+x[4],x[5]+x[6] 的值。
    小A知道x的3-划分序列,即分别知道x[1]+x[2]+x[3] ,x[4]+x[5]+x[6] 的值。
    小A可以知道x[3],x[4]的值,个数为2.

    #题解
    这题在考场的时候由于T1水题的错误理解导致心态崩了。
    于是T3(这道题)就很少时间+很少心情去想。
    只是在纸上推了推,然后就几乎弃掉了。

    然而我推出了个公式——
    满足xk[i]-1=yk[j]时,大概是对答案造成n div (k[i]*k[j])的贡献。

    然而这就是关键!

    满足的式子我们可以换一下,变成拓展欧几里得来求。
    然后那个答案其实我算错了:是
    1+(n-k[i]*x)/(k[i]*k[j])
    然后,这样可以在一个m方级别的时间复杂度完成。

    但是,我们可以很难受地发现,会有一些计算重复。
    怎么办?我们就直接搞容斥原理即可。
    原式:ax-by=1
    那么我们就可以分为3类——
    分到a集合。
    分到b集合。
    不分。
    这样就可以状压DP。
    其实dfs即可,更好写。

    我们就看看如何容斥。
    首先,我们可以发现,当两个集合的和为偶数,则是对答案造成贡献。奇数则为删除重复。
    这个可以自己推一推。
    然后,我们每次更新答案的时候,就把a集合的数全部求lcm。b集合的数全部求lcm。
    然后两个拓展欧几里得一下。
    就可以更新啦~~~

    但是,看到第一个样例。这种情况要搞一搞。实际上直接把n丢在dfs的队列里面即可。

    然而,我蜜汁错误90.有一点一直没调出来,只好低(man)头(xing)叹(huan)息(xi)地打了个表。
    如果有大佬找到错误了,可以在下面帮我求解。万分感谢。

    错误的代码

    var
            i,j,k,l,n,m:longint;
            zb,yb,gs1,gs2:int64;
            x,y,aa,bb,cc,dd,ans:int64;
            a,zt:array[1..11] of int64;
    function exgcd(a,b:int64):int64;
    var
            r,z:int64;
    begin
            if b=0 then
            begin
                    x:=1;
                    y:=0;
                    exit(a);
            end;
            r:=exgcd(b,a mod b);
            z:=x;
            x:=y;
            y:=z-a div b*y;
            exit(r);
    end;
    function gcd(x,y:int64):int64;
    begin
            if y=0 then exit(x);
            exit(gcd(y,x mod y));
    end;
    function lcm(x,y:int64):int64;
    var
            i:qword;
    begin
            i:=x*y;
            exit(i div gcd(x,y));
    end;
    procedure dfs(dep:longint);
    var
            j,k,l:longint;
            i:int64;
    begin
            if dep>m+1 then
            begin
                    if (gcd(zb,yb)=1) and (gs1>0) and (gs2>0) then
                    begin
                            if (gs1+gs2) mod 2=0 then
                            begin
                                    x:=0;
                                    y:=0;
                                    aa:=zb;
                                    bb:=-yb;
                                    cc:=1;
                                    dd:=exgcd(aa,bb);
                                    if cc mod dd=0 then
                                    begin
                                            x:=x*cc div dd mod (bb div dd);
                                            if x<0 then
                                            x:=x+abs(bb div dd);
                                            y:=(cc-aa*x) div bb;
                                            if (aa*x<=n) then
                                            if y>0 then ans:=ans+1+(n-aa*x+1) div (aa*(-bb));
                                    end;
                            end
                            else
                            begin
                                    x:=0;
                                    y:=0;
                                    aa:=zb;
                                    bb:=-yb;
                                    cc:=1;
                                    dd:=exgcd(aa,bb);
                                    if cc mod dd=0 then
                                    begin
                                            x:=x*cc div dd mod (bb div dd);
                                            if x<0 then
                                            x:=x+abs(bb div dd);
                                            y:=(cc-aa*x) div bb;
                                            if (aa*x<=n) then
                                            if y>0 then ans:=ans-1-(n-aa*x+1) div (aa*(-bb));
                                    end;
                            end;
                    end;
            end
            else
            begin
                    i:=zb;
                    zb:=lcm(zb,a[dep]);
                    inc(gs1);
                    if zb<n then
                    dfs(dep+1);
                    zb:=i;
                    i:=yb;
                    yb:=lcm(yb,a[dep]);
                    dec(gs1);
                    inc(gs2);
                    if yb<n then
                    dfs(dep+1);
                    yb:=i;
                    dec(gs2);
                    dfs(dep+1);
            end;
    end;
    begin
            assign(input,'sazetak.in');reset(input);
            assign(output,'sazetak.out');rewrite(output);
            readln(n,m);
            for i:=1 to m do
            begin
                    read(a[i]);
            end;
            a[m+1]:=n;
            zb:=1;
            yb:=1;
            dfs(1);
            writeln(ans);
    end.
    
    我活在这夜里。无论周围多么黑暗,我都要努力发光!我相信着,终有一天,我会在这深邃的夜里,造就一道最美的彩虹。
  • 相关阅读:
    httpclient的并发连接问题
    Java中使用多线程、curl及代理IP模拟post提交和get访问
    有强大的cURL,忘掉httpclient的吧!
    JavaScript正则表达式在不同浏览器中可能遇到的问题
    Meta对照表
    IntelliJ IDEA 下的svn配置及使用的非常详细的图文总结
    虚拟机centos7服务器下,启动oracle11g数据库和关闭数据库
    Step 4: Install and Configure Databases
    docker 中部署一个springBoot项目
    docker保存对容器的修改
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11148399.html
Copyright © 2011-2022 走看看