17.10.6B组总结

来源:互联网 发布:手机商城模板php 编辑:程序博客网 时间:2024/06/10 02:53

17.10.6B组总结

T1

完美签到题,先将问题转化为1~r中的数减去1~l-1中的数,再根据容斥原理,用递归,偶数加,奇数减,完美AC……

var        n,l,r,i,j,ll,rr,len,ans:longint;        a,f:array[0..20]of int64;function gcd(x,y:int64):int64;begin        if x mod y=0 then                exit(y);        exit(gcd(y,x mod y));end;function dg(t,sum,sf:longint;h:int64):longint;begin        if t>n then        begin                if sum>0 then                        inc(f[sum],sf div h);                exit;        end;        dg(t+1,sum,sf,h);        dg(t+1,sum+1,sf,h*a[t] div gcd(h,a[t]));end;function find(ss:int64):int64;var        i,rr,len,s:longint;begin        fillchar(f,sizeof(f),0);        find:=0;        dg(1,0,ss,1);        for i:=1 to n do                if i mod 2=1 then                        inc(find,f[i])                else                        dec(find,f[i]);        exit(ss-find);end;begin        readln(n,l,r);        for i:=1 to n do                read(a[i]);        writeln(find(r)-find(l-1));end.

这题居然在今天做提高组15年初赛题目里出现了,无语O__O “…

T2

这是今天比赛里最难的题了,开始想到了50分的状压DP,无奈调不出来,只好弃疗;
正解也很简单,就直接设f[i,j]表示做到了第i行,二进制状态为j,再预处理出该状态之前的状态,轻松搞定50分。
接着发生了神奇的一幕,M在后50分中居然缩小了,于是问题就变成了两部分。我们发现其实对于一个状态i,转移到下一个状态j之后,转移的方法不会改变,于是很自然的想到了矩阵乘法。
多设一个a数组,来将每一个预处理出的前状态与现状态塞到a里面。再用快速幂搞一搞就好了,记得n很大,要用高精度除,最好压位。
大致代码:

const        mo=1000000007;        e=1000000000000000;type        arr=array[0..32]of int64;        ju=array[0..32,0..32]of int64;var        n,m,i,j,k,tot:longint;        s,tn,tm:ansistring;        tmp:string;        f:array[0..100,0..10000]of int64;        jl:array[0..15000,1..2]of int64;        a,ans:ju;        g:arr;procedure dg(x:longint;last,now:int64);begin        if x>m then                exit;        if x=m then        begin                inc(tot);                jl[tot,1]:=last;                jl[tot,2]:=now;        end;        dg(x+1,(last<<1)+1,now<<1);        dg(x+1,last<<1,(now<<1)+1);        dg(x+2,(last<<2)+3,(now<<2)+3);end;function did(x,y:ju):ju;var        i,j,k:longint;begin        fillchar(did,sizeof(did),0);        for i:=0 to 1<<m do                for j:=0 to 1<<m do                        for k:=0 to 1<<m do                                did[i,j]:=(did[i,j]+x[i,k]*y[k,j]) mod mo;end;procedure divv(var x:arr);var        i,tt:longint;begin        tt:=0;        for i:=x[0] downto 1 do        begin                inc(x[i],tt*e);                tt:=x[i] mod 2;                x[i]:=x[i] div 2;                if x[i]=0 then                        x[0]:=i-1;        end;end;procedure quick(r:arr);begin        fillchar(ans,sizeof(ans),0);        for i:=0 to 1<<m do                ans[i,i]:=1;        while r[0]>0 do        begin                if r[1] and 1=1 then                        ans:=did(ans,a);                a:=did(a,a);                divv(r);        end;end;begin        readln(s);        tn:=copy(s,1,pos(' ',s)-1);        tm:=copy(s,pos(' ',s)+1,length(s)-pos(' ',s));        val(tm,m);        dg(0,0,0);        if (length(tn)<=2)or(tn='100') then        begin                val(tn,n);                if n*m mod 2=1 then                begin                        writeln(0);                        halt;                end;                f[0,(1<<m)-1]:=1;                for i:=1 to n do                        for j:=1 to tot do                                f[i,jl[j,2]]:=(f[i,jl[j,2]]+f[i-1,jl[j,1]]) mod mo;                writeln(f[n,(1<<m)-1]);                halt;        end;        for i:=1 to tot do                a[jl[i,1],jl[i,2]]:=1;        fillchar(g,sizeof(g),0);        tmp:='';        i:=length(tn);        j:=0;        while i>=1 do        begin                tmp:=tn[i]+tmp;                inc(j);                if j=15 then                begin                        inc(g[0]);                        val(tmp,g[g[0]]);                        j:=0;                        tmp:='';                end;                dec(i);        end;        if j>0 then        begin                inc(g[0]);                val(tmp,g[g[0]]);        end;        quick(g);        m:=(1<<m)-1;        writeln(ans[m,m] mod mo);end.

T3

暴力都能过,纪中数据水呀!
正解是双向队列+栈维护,可我比赛只得了70,莫名其妙。
对了,c++有个特别好用的自带翻转函数,比正解还快。

#include<cstdlib>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;int q[5000010];int c,k,top;int main(){    scanf("%d",&c);    scanf("%d",&k);    while(k)     {        if(k==1)         {            int e;            scanf("%d",&e);            q[++top]=e;        }        if(k==2)         {            if(top<1)                 printf("Error: the stack is empty!\n");            else                 printf("%d\n",q[top]),top--;        }        if (k==3)         {            if(top<c)                 printf("Error: less than %d elements in the stack!\n",c);            else                 reverse(q+1+top-c,q+1+top);        }        scanf("%d",&k);    }    return 0;}

T4

比赛打了十个表懵逼,后来蒙蒙地打了个递推上去,a掉了,听刘犇讲好像是什么奇怪的东西,懵逼 *2。
推一波式子后,发现:

f[i]=(j=1j<if[j]+i)÷(i1)

答案f[n],显而易见。
记得f[1]=0;