17.10.6B组总结

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;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值