欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

2017.8.26 noip模拟赛 总结

程序员文章站 2022-03-01 18:44:44
...

装作有题目的样子。。。

由于是自己的题,题面这种东西就不太好往上面放。。

标准NOIP难度,第一题约等于day2T1,第二题约等于day2T2,第三题约等于day1T3。

第一道题:

由于和bzoj上某道题比较类似,放个那道题的链接吧。。

题目

总之,就是一道加了一点细节的递推题,想到递推矩阵会发生变化后就比较好想了。而且,这类题目还很好对拍,是比较稳的了。

#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#define mod 1000000007
using namespace std;
long long n,tmp,k;
long long f[20];
struct matrix{
    int h;
    int l;
    long long data[5][5];
};
matrix a,b,c;
matrix multiply(matrix A,matrix B)
{
    matrix ans;
    ans.h=A.h,ans.l=B.l;
    for(int i=1;i<=ans.h;i++)
        for(int j=1;j<=ans.l;j++)
            ans.data[i][j]=0;
    for(int i=1;i<=ans.h;i++)
        for(int j=1;j<=ans.l;j++)
            for(int k=1;k<=A.l;k++)
                ans.data[i][j]=(ans.data[i][j]+A.data[i][k]*B.data[k][j])%mod;
    return ans;
}
void write(matrix A)
{
    for(int i=1;i<=A.h;i++)
    {
        for(int j=1;j<=A.l;j++)
            cout<<A.data[i][j]<<" ";
        cout<<endl;
    }
}
matrix ksm(matrix A,long long B)
{
    matrix ans;
    ans.h=A.h,ans.l=A.l;
    for(int i=1;i<=ans.h;i++)
        for(int j=1;j<=ans.l;j++)
            ans.data[i][j]=(i==j);
    while(B)
    {
        if(B&1)ans=multiply(ans,A);
        B>>=1;
        A=multiply(A,A);
    }
    return ans;
}
int main()
{
    freopen("math.in","r",stdin);
    freopen("math.out","w",stdout);
    cin>>n;
    if(n<=100000)
    {
        for(int i=1;i<=min((long long)9,n);i++)
            tmp=(tmp*10+i)%mod;
        for(int i=10;i<=min((long long)99,n);i++)
            tmp=(tmp*100+i)%mod;
        for(int i=100;i<=min((long long)999,n);i++)
            tmp=(tmp*1000+i)%mod;
        for(int i=1000;i<=min((long long)9999,n);i++)
            tmp=(tmp*10000+i)%mod;
        for(int i=10000;i<=min((long long)99999,n);i++)
            tmp=(tmp*100000+i)%mod;
        for(int i=100000;i<=min((long long)999999,n);i++)
            tmp=(tmp*1000000+i)%mod;
        cout<<tmp%mod;
        return 0;
    }
    f[0]=1;
    for(int i=1;i<=18;i++)f[i]=f[i-1]*10;
    a.h=1,a.l=3,a.data[1][1]=0;a.data[1][2]=1;a.data[1][3]=1;
    b.h=3,b.l=3,b.data[1][1]=1;b.data[1][2]=0;b.data[1][3]=0;
    b.data[2][1]=1;b.data[2][2]=1;b.data[2][3]=0;
    b.data[3][1]=0;b.data[3][2]=1;b.data[3][3]=1;
    for(int i=1;n>0;i++)
    {
        b.data[1][1]=f[i]%mod;
        if(f[i]==0)k=n;
        else k=min(n,f[i]-f[i-1]);
        c=ksm(b,k);
        a=multiply(a,c);
        n-=k;
    }
    cout<<a.data[1][1];
    return 0;
} 

贴个代码,当然,为了更加稳健,加了一个,if语句,考试技巧啊。。

不过,noipt1真的会考矩阵吗233(希望不是个flag)。。。

第二道题:

一道和中位数相关的题,求每个节点到根的路径中的所有数的中位数。。。

根据中位数定义,就是求树上的区间第k大。。。,由于是到根,自然而然就想到了用dfs序,我习惯用括号序列,就是入栈时插入一次,出栈时再插入一次。然后,第一次出现给它存入权值线段树中,然后get答案,第二次出现就弹出来。

#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#define N 100000
using namespace std;
int n,A[N+1],B[N+1],tmp[N+1],m;
int first[N+1],nex[2*N+1],to[2*N+1],siz;
int seq[2*N+1],cnt,x,y; 
int tot,f[N+1],k;
bool E[N+1];
struct Tree{
    int l;
    int r;
    int data;
};Tree T[N*4+1];
inline void add(int x,int y)
{
    nex[siz]=first[x];
    first[x]=siz;
    to[siz]=y;
    siz++;
}
inline char nc()
{
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
    int x=0,b=1;
    char c=nc();
    for(;!(c<='9'&&c>='0');c=nc())if(c=='-')b=-1;
    for(;c<='9'&&c>='0';c=nc())x=x*10+c-'0';
    return x*b;
}
void build(int rt,int l,int r)
{
    T[rt].l=l,T[rt].r=r;
    if(l==r)return;
    int mid=(l+r)/2;
    build(rt*2,l,mid),build(rt*2+1,mid+1,r);
}
void pushup(int rt)
{
    T[rt].data=T[rt*2].data+T[rt*2+1].data;
}
void modify(int rt,int pos,int val)
{
    if(T[rt].l==pos&&T[rt].r==pos)
    {
        T[rt].data+=val;
        return;
    }
    int mid=(T[rt].l+T[rt].r)/2;
    if(pos<=mid)modify(rt*2,pos,val);
    else modify(rt*2+1,pos,val);
    pushup(rt);
}
int find(int k)
{
    int pos=1;
    while(T[pos].l!=T[pos].r)
    {
        if(k<=T[pos*2].data)pos=pos*2;
        else k-=T[pos*2].data,pos=pos*2+1;
    }
    return T[pos].l;
}
inline void DFS(int x,int fa)
{
    seq[++cnt]=x;
    for(int i=first[x];i!=-1;i=nex[i])
    {
        int u=to[i];
        if(u==fa)continue;
        DFS(u,x);
    }
    seq[++cnt]=x;
}
int main()
{
    freopen("caculattree.in","r",stdin);
    freopen("caculattree.out","w",stdout);
    n=read();
    for(int i=1;i<=n;i++)A[i]=read();
    for(int i=1;i<=n;i++)B[i]=A[i],tmp[i]=A[i];
    sort(tmp+1,tmp+n+1);
    m=unique(tmp+1,tmp+n+1)-tmp-1;
    for(int i=1;i<=m;i++)A[i]=tmp[i];
    for(int i=1;i<=n;i++)B[i]=lower_bound(tmp+1,tmp+m+1,B[i])-tmp;
    memset(first,-1,sizeof(first));
    for(int i=1;i<n;i++)
    {
        x=read(),y=read();
        add(x,y),add(y,x);
    }
    DFS(1,0);build(1,1,n);
    for(int i=1;i<=cnt;i++)
    {
        if(!E[seq[i]])
        {
            tot++;
            modify(1,B[seq[i]],1);
            E[seq[i]]=true;
            if(tot%2==0)k=tot/2;
            else k=tot/2+1;
            f[seq[i]]=find(k);
        }
        else modify(1,B[seq[i]],-1),tot--;
    }
    for(int i=1;i<=n;i++)printf("%d ",A[f[i]]);
    return 0;
} 

再次吐槽,这真的是t2吗。。。

天天爱跑步。。。

第三题:

一眼望去,就是一道状压dp的题。

但是,我不会呀233。

打个暴力就跑吧。。。
不愧是t3。。。

没有代码。。

等待了好久好久,途中吃了一顿火锅233。

成绩出来了,很稳呀,该拿的分都拿了。

这样的话,在SN弱省一等奖还是可以的吧。。。