2017.10.19 模拟赛

题目链接

T1

经过打表发现f(x)=x (x>=2) f(1)=2;

然后问题就变为 ∑f(i)^k

拉格朗日插值法。。学习地址

#include <cstdio>
#include <cctype>
#define Mod 998244353

inline void read(register int &x)
{
    register char ch=getchar();
    for(x=0;!isdigit(ch);ch=getchar());
    for(;isdigit(ch);x=x*10+ch-'0',ch=getchar());
}
int l,r,k,ans;
inline int ksm(register int a,register int b)
{
    int r=1,base=a;
    for(;b;b>>=1,base=1ll*base*base%Mod)
     if(b&1) r=1ll*r*base%Mod;
    return r%Mod;
}
int main(int argc,char *argv[])
{
    freopen("count.in","r",stdin);
    freopen("count.out","w",stdout);
    scanf("%d%d%d",&l,&r,&k);
    for(register int i=l;i<=r;++i)
    {
        register int f;
        if(i==1||i==2) f=2;
        else f=i;
        ans=(ans%Mod+ksm(f,k))%Mod;
    }
    printf("%d
",ans);
    fclose(stdin);
    fclose(stdout);
    return 0;
}
考场20分代码
#include <cstring>
#include <ctime>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
 
using namespace std;
 
const int Mod=998244353;
const int MAXK=1000000;
 
int power(int x,int k)
{
    int ret=1;
    while (k)
    {
        if (k&1) ret=1LL*ret*x%Mod;
        x=1LL*x*x%Mod;
        k>>=1;
    }
    return ret;
}
 
int k;
 
int f[MAXK+10];
 
int pre[MAXK+10],suf[MAXK+10];
 
int jc[MAXK+10],K[MAXK+10];
 
int cnt(int n)
{
    if (n==0) return 0;
    int ans=0;
    if (n<=k+10 || n<=MAXK)
    {
        for (int i=1; i<=n; i++) ans=(K[i]+ans)%Mod;
    }
    else
    {
        pre[0]=1;
        for (int i=1; i<=k+2; i++) pre[i]=1LL*pre[i-1]*(n-i)%Mod;
 
        suf[k+3]=1;
        for (int i=k+2; i>=1; i--) suf[i]=1LL*suf[i+1]*(n-i)%Mod;
 
        int l=k+1,r=0,flag=((k+1)&1)?(-1):(1);
        for (int i=1; i<=k+2; i++)
        {
            int s=1LL*pre[i-1]*suf[i+1]%Mod,m=1LL*(flag*jc[l]+Mod)*jc[r]%Mod;
            ans=(1LL*f[i]*s%Mod*power(m,Mod-2)%Mod+ans)%Mod;
            l--;
            r++;
            flag*=-1;
        }
    }
    ans=((ans+K[2])%Mod-1+Mod)%Mod;
    return ans;
}
 
int L,R;
 
void init()
{
    cin>>L>>R>>k;
    for (int i=1; i<=MAXK+5; i++) K[i]=power(i,k);
 
    jc[0]=1;
    for (int i=1; i<=k+2; i++) jc[i]=1LL*jc[i-1]*i%Mod;
    for (int i=1; i<=k+2; i++) f[i]=(f[i-1]+K[i])%Mod;
 
    cout<<(cnt(R)-cnt(L-1)+Mod)%Mod;
    return ;
}
 
int main()
{
    freopen("count.in","r",stdin);
    freopen("count.out","w",stdout);
    init();
    fclose(stdin);
    fclose(stdout);
    //fprintf(stderr,"%.3lf
",1.0*clock()/(1.0*CLOCKS_PER_SEC));
    return 0;
}
std

T2

题意转化为求最大的区间长度使得这段区间和减k>=0
首先做前缀和,可知若当前到了k,i<j<k && sum[i]<sum[j]则j一定不可能比i更优
用单调栈维护这个过程。然后倒序更新答案即可。

#include<cstdlib>
#include<cstdio>
#include<cctype>
#define N 1000005
typedef long long LL;
int n,m,len,maxv,a[N];
LL sum[N];
inline void read(int &x)
{
    register char ch=getchar();
    for(x=0;!isdigit(ch);ch=getchar());
    for(;isdigit(ch);x=x*10+ch-'0',ch=getchar());
}
inline int max(int a,int b) {return a>b?a:b;}
int main()
{
    freopen("blocks.in","r",stdin);
    freopen("blocks.out","w",stdout);
    read(n);read(m);
    for(int i=1;i<=n;i++)
    {
        read(a[i]);
        sum[i]=sum[i-1]+a[i];
        maxv=max(maxv,a[i]);
    }
    for(int k,i=1;i<=m;i++)
    {
        read(k);
        if(k>maxv) {i==m?printf("0
"):printf("0 ");continue;} 
        for(register int l=1;l<=n;++l)
            for(register int r=l;r<=n;++r)
            {
                int tmp=r-l+1;
                if((sum[r]-sum[l-1]-tmp*k)>=0) len=max(len,tmp);
            }
        i==m?printf("%d
",len):printf("%d ",len);len=0;
    }
    fclose(stdin); fclose(stdout);
    return 0;
}
考场40分代码
#include<iostream>
#include<cstdio>
#include<cstring>

#define N 1000007

using namespace std;
long long sum[N];
int a[N],st[N],top,n,m,cnt;

inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

void solve(int k)
{
    top=1;int res=0;
    for(int i=1;i<=n;i++) 
    {
        sum[i]=sum[i-1]+a[i]-k;
        if(!top || sum[st[top]]>sum[i]) st[++top]=i;
    }
    for(int i=n;i>=1;i--) 
    {
        while(top && sum[i]>=sum[st[top]]) top--;
        res=max(res,i-st[top+1]);
    }
    printf("%d ",res);
}

int main()
{
    freopen("blocks.in","r",stdin);
    freopen("blocks.out","w",stdout);
    n=read();m=read();
    for(int i=1;i<=n;i++) a[i]=read();
    while(m--) solve(read());
    return 0;
}
std

T3

将字符串倒序插入trie树,问题就转换成了若干字符串结束的LCA深度
倍增维护LCA,每插入一个字符串,处理一次fa数组就可以了
当然这题也可以哈希+二分

#include <iostream>
#include <cstring>
#include <string>
#include <cctype>
#include <cstdio>
#include <vector>
#define N 50005
#define L 1000005
using namespace std;
inline void read(int &x)
{
    register char ch=getchar();
    for(x=0;!isdigit(ch);ch=getchar());
    for(;isdigit(ch);x=x*10+ch-'0',ch=getchar());
}
int n,m,a[N],len[N];
string str[N];
inline int min(int a,int b) {return a>b?b:a;}
int main(int argc,char *argv[])
{
    freopen("biology.in","r",stdin);
    freopen("biology.out","w",stdout);
    read(n);read(m);
    for(int i=1;i<=n;++i) cin>>str[i],len[i]=str[i].length();
    for(register int opt,x;m--;)
    {
        read(opt);
        if(opt==1) cin>>str[++n],len[n]=str[n].length();
        else 
        {
            read(x);
            int limit=0x7fffffff;
            for(int i=1;i<=x;++i) read(a[i]),limit=min(limit,len[a[i]]);
            register int ans=limit;
            for(register int i=0;i<=limit;++i)
            {
                string s=str[a[1]];
                register char ch=s[len[a[1]]-i-1];
                bool flag=false;
                for(register int j=2;j<=x;++j)
                {
                    string y=str[a[j]];
                    if(y[len[a[j]]-i-1]!=ch)
                    {
                        flag=true;
                        break;
                    }
                }
                if(flag)
                {
                    ans=i;
                    break;
                }
            }
            printf("%d
",ans);
        }
    }
    fclose(stdin); fclose(stdout);
    return 0;
}
考场60分代码
#include <cstring>
#include <cstdio>
#include <cctype>
#define N 1000010
int n,m,tot=1,trie[N][28],dad[N][25],pos[N],dep[N];
char s[10005];
void ins(int num)
{
    int p=1,l=strlen(s+1);
    for(int i=l;i;--i)
    {
        int id=s[i]-'a';
        if(!trie[p][id])
        {
            trie[p][id]=++tot;
            dep[tot]=dep[p]+1;dad[tot][0]=p;
            for(int j=1;j<=20;++j) dad[tot][j]=dad[dad[tot][j-1]][j-1];
        }
        p=trie[p][id];
    }
    pos[num]=p;
}
void swap(int &m,int &n)
{
    int tmp=n;
    n=m;
    m=tmp;
}
int lca(int x,int y)
{
    if(dep[x]>dep[y]) swap(x,y);
    for(int i=20;i>=0;--i) 
    if(dep[dad[y][i]]>=dep[x])
     y=dad[y][i];
    if(x==y) return x;
    for(int i=20;i>=0;--i) 
    if(dad[y][i]!=dad[x][i])
     y=dad[y][i],x=dad[x][i];
    return dad[x][0];
}
int main(int argc,char *argv[])
{
    freopen("biology.in","r",stdin);
    freopen("biology.out","w",stdout);
    scanf("%d%d",&n,&m);
    dep[0]=-1;
    for(int i=1;i<=n;++i) scanf("%s",s+1),ins(i);
    for(int opt,x,y,v;m--;)
    {
        scanf("%d",&opt);
        if(opt==1)
        {
            scanf("%s",s+1);
            ins(++n);
        }
        else
        {
            scanf("%d%d",&x,&y);
            int z=pos[y];
            for(int i=2;i<=x;++i)
            {
                scanf("%d",&v);
                z=lca(z,pos[v]);
            }
            printf("%d
",dep[z]);
        }
    }
    fclose(stdin); fclose(stdout);
    return 0;
}
std
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

typedef unsigned long long ll;

const int maxlen=1000005,maxn=150005,hpos=29;

int n,m,S[maxn],T[maxn],len[maxn],nowlen,top,Stack[maxn];

char Arc[maxlen];

ll Hash[maxlen];

inline void read(int &now)
{
    char Cget;
    now=0;
    while((Cget=getchar())>'9'||Cget<'0');
    while(Cget>='0'&&Cget<='9')
    {
        now=now*10+Cget-'0';
        Cget=getchar();
    }
}

inline bool check(int lit)
{
    ll tmp=Hash[T[Stack[1]]-lit+1];
    for(int i=2;i<=top;i++)
        if(Hash[T[Stack[i]]-lit+1]!=tmp)
            return false;
    return true;
}

int main()
{
//    freopen("data.txt","r",stdin);
    freopen("biology.in","r",stdin);
    freopen("biology.out","w",stdout);
    read(n);
    read(m);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",Arc+nowlen);
        len[i]=strlen(Arc+nowlen);
        S[i]=nowlen;
        T[i]=nowlen+len[i]-1;
        nowlen+=len[i];
        Hash[T[i]]=Arc[T[i]]-'a'+1;
        for(int v=T[i]-1;v>=S[i];v--)
            Hash[v]=Hash[v+1]*hpos+(Arc[v]-'a'+1);
    }
    for(int i=1,op,l,r,mid,res;i<=m;i++)
    {
        read(op);
        if(op==1)
        {
            ++n;
            scanf("%s",Arc+nowlen);
            len[n]=strlen(Arc+nowlen);
            S[n]=nowlen;
            T[n]=nowlen+len[n]-1;
            nowlen+=len[n];
            Hash[T[n]]=Arc[T[n]]-'a'+1;
            for(int v=T[n]-1;v>=S[n];v--)
                Hash[v]=Hash[v+1]*hpos+(Arc[v]-'a'+1);
        }
        else
        {
            read(top);
            l=1,r=maxlen,mid,res=0;
            for(int v=1;v<=top;v++)
            {
                read(Stack[v]);
                r=std::min(r,len[Stack[v]]);
            }
            while(l<=r)
            {
                mid=l+r>>1;
                if(check(mid))
                {
                    res=mid;
                    l=mid+1;
                }
                else
                    r=mid-1;
            }
            printf("%d
",res);
        }
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}
某m姓大佬的hash
原文地址:https://www.cnblogs.com/ruojisun/p/7692354.html