TJOI2018游记

D1T1 - 数学计算

直接用线段树/平衡树维护所有数的积即可。我思想僵化写了一个数学方法...应该是能做\(\bmod\)所有数的乘除法。
时间复杂度\(O(nlogn)\)

D1T2 - 智力竞赛

二分答案+最小可相交路径覆盖。题意有点乱...

D1T3 - party

Icefox orz 是我不会的DDP呢。首先列出最长公共子序列的DP方程,\(dp[i][j]\)表示\(a_1\)的前\(i\)位与\(a_2\)的前\(j\)位的LCS长度:
\[ dp[i][j]=max(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]+[a_1[i]=a_2[j]]) \] 观察到\(dp[i][j]\)只会比\(dp[i][j-1]\)大0/1,所以将这个DP数组压成一个二进制数进行DP。\(f[i][s]\)表示对于一个长度为\(i\)的兑奖串,此时的DP数组的状态为\(s\)时的方案数。预处理出DP数组根据第\(i\)位的选择会转移到什么状态,就可以做啦。由于要求不能出现“NOI”所以再加一维记录前两位的状态就好啦。
时间复杂度\(O(n2^k)\)

D2T1 - str

\(dp[i][j]\)表示用了前\(i\)种串,在位置\(j\)匹配结束的串的个数。那么对于第\(i+1\)种串用KMP得到其能匹配在哪些位置,就可以转移到\(dp[i+1]\)了。
时间复杂度\(O(|s|\Sigma a)\)

D2T2 - xor

基本是个可持久化trie树裸题。不过好像Windows下DFS会爆栈?
时间复杂度\(O(n+30Q)\)

D3T3 - 教科书般的亵渎

玩过炉石的应该很容易看懂题。再加上我最近经常玩变节咆哮魔亵渎术233
最终目标是求\(S(n,k)=\sum_{i=1}^n i^k\)。有两种方法:
\[\begin{align*} (n+1)^{k+1}-n^{k+1} &= \binom{k+1}{1}n^k+\binom{k+1}{2}n^{k-1}+...+\binom{k+1}{k+1}n^0 \\ n^{k+1}-(n-1)^{k+1} &= \binom{k+1}{1}(n-1)^k+\binom{k+1}{2}(n-1)^{k-1}+...+\binom{k+1}{k+1}(n-1)^0 \\ &... \\ 2^{k+1}-1^{k+1} &= \binom{k+1}{1}1^k+\binom{k+1}{2}1^{k-1}+...+\binom{k+1}{k+1}1^0 \\ \end{align*}\] 相加,得
\[\begin{align*} (n+1)^{k+1}-1 &= \binom{k+1}{1}S(n,k)+\binom{k+1}{2}S(n,k-1)+...+\binom{k+1}{k+1}S(n,0) \\ S(n,k) &= \frac{1}{k+1}((n+1)^{k+1}-\sum_{i=2}^{k+1}\binom{k+1}{i}S(n,k+1-i)-1) \end{align*}\] 于是我们就可以在\(O(k^2)\)的时间内求出\(S(n,k)\)
另一种做法是利用伯努利数
首先有
\[ S(n,k)= \frac{1}{k+1} \sum_{i=1}^{k+1}\binom{k+1}{i}B_{k+1-i}(n+1)^i \]其中\(B\)是伯努利数,伯努利数满足\(B_0=1\),对于\(n>0\)
\[ \sum_{i=0}^{n}\binom{n+1}{i}B_i=0 \] 然后就可以求了。不要问我为什么,我也不知道!

Code

D1T1

#include <cstdio>
typedef long long lint;
inline char gc()
{
    static char now[1<<16],*s,*t;
    if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;}
    return *s++;
}
inline int read()
{
    int x=0; char ch=gc();
    while(ch<'0'||'9'<ch) ch=gc();
    while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x;
}
const int N=1e4+10;
const int N1=1e5+10;
int cntP,pr[N1]; bool notP[N1];
int p1[N1],phi[N1];
void init()
{
    phi[1]=1;
    for(lint i=2;i<=1e5;i++)
    {
        if(!notP[i])
        {
            pr[++cntP]=i; p1[i]=i,phi[i]=i-1;
            for(lint j=i*i;j<=1e5;j*=i) p1[j]=j,phi[j]=(i-1)*(j/i);
        }
        for(int j=1;j<=cntP;j++)
        {
            if(i*pr[j]>1e5) break;
            int x=i*pr[j]; notP[x]=true;
            if(i%pr[j]) p1[x]=pr[j],phi[x]=phi[i]*(pr[j]-1);
            else {p1[x]=p1[i]*pr[j],phi[x]=phi[p1[x]]*phi[x/p1[x]]; break;}
        }
    }
}
int pow(int x,int y,int P)
{
    while(x<0) x+=P; 
    lint r=1,t=x;
    for(int i=y;i;i>>=1,t=t*t%P) if(i&1) r=r*t%P;
    return r;
}
int cnt,p[N],q[N]; lint m[N],a[N],k[N];
int getX()
{
    int a1=0,m1=1,phi1=1;
    for(int i=1;i<=cnt;i++)
    {
        int m2=m[i],a2=(k[i]>=q[i])?0:(a[i]*pow(p[i],k[i],m[i]));
        int phi2=(p[i]-1)*(m[i]/p[i]);
        lint t=1LL*a1*m2-1LL*a2*m1;
        while(t<0) t+=m1*m2;
        a1=t*pow(m2-m1,phi1*phi2-1,m1*m2)%(m1*m2);
        m1=m1*m2; phi1=phi1*phi2;
    }
    return a1;
}
int pos[N1];
void work0(int Q,int P)
{
    int ans=1;
    for(int owo=1;owo<=Q;owo++)
    {
        int opt=read(),x=read();
        pos[owo]=x;
        if(opt==1) ans=(lint)ans*x%P;
        else ans=(lint)ans*pow(pos[x],P-2,P)%P;
        printf("%d\n",ans);
    }
}
int main()
{
    freopen("cal.in","r",stdin);
    freopen("cal.out","w",stdout);
    int task=read(); init();
    while(task--)
    {
        
    int Q=read(),mod=read();
    cnt=0;
    for(int i=1,t=mod;i<=cntP+1;i++)
    {
        if(i==cntP+1&&t>1)
        {
            cnt++,p[cnt]=t,q[cnt]=1,m[cnt]=t,a[cnt]=1,k[cnt]=0;
            break;
        }
        if(t<pr[i]) break;
        if(t%pr[i]==0) cnt++,p[cnt]=pr[i],q[cnt]=0,m[cnt]=1,a[cnt]=1,k[cnt]=0;
        while(t%pr[i]==0) t/=pr[i],q[cnt]++,m[cnt]*=pr[i];
    }
    if(cnt<=1) {work0(Q,mod); continue;}
    for(int owo=1;owo<=Q;owo++)
    {
        int opt=read(),x=read();
        pos[owo]=x;
        if(opt==1)
        {
            for(int i=1;i<=cnt;i++)
            {
                int t=x;
                while(t%p[i]==0) t/=p[i],k[i]++;
                a[i]=(lint)a[i]*t%m[i];
            }
        }
        else
        {
            for(int i=1;i<=cnt;i++)
            {
                int t=pos[x];
                while(t%p[i]==0) t/=p[i],k[i]--;
                a[i]=(lint)a[i]*pow(t,(p[i]-1)*(m[i]/p[i])-1,m[i])%m[i];
            }
        }
        //for(int i=1;i<=cnt;i++) printf("=%d (mod %d) k=%d\n",a[i],m[i],k[i]);
        printf("%d\n",getX());
    }
    
    }
    return 0;
}

D1T2

//智力竞赛
#include <algorithm>
#include <cstdio>
#include <cstring>
using std::sort;
inline char gc()
{
    static char now[1<<16],*s,*t;
    if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;}
    return *s++;
}
inline int read()
{
    int x=0; char ch=gc();
    while(ch<'0'||'9'<ch) ch=gc();
    while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x;
}
const int N=600;
int n,m,w[N]; bool ed[N][N],e[N][N];
int map[N];
struct rec{int w,id;} r[N];
bool cmpW(rec x,rec y) {return x.w<y.w;}
int n1; int link[N]; bool used[N];
bool find(int u)
{
    for(int v=1;v<=n1;v++)
    {
        if(!e[u][v]||used[v]) continue;
        used[v]=true;
        if(!link[v]||find(link[v])) {link[v]=u; return true;}
    }
    return false;
}
int match()
{
    int res=0; memset(link,0,sizeof link);
    for(int u=1;u<=n1;u++)
    {
        memset(used,0,sizeof used);
        if(find(u)) res++;
    }
    return res;
}
bool check(int x)
{
    n1=x;
    memset(e,false,sizeof e);
    for(int u=1;u<=n1;u++)
        for(int v=1;v<=n1;v++)
            e[u][v]=ed[u][v];
    for(int k=1;k<=n1;k++)
        for(int u=1;u<=n1;u++)
            for(int v=1;v<=n1;v++)
                e[u][v]|=e[u][k]&&e[k][v];
    return n1-match()<=m;
}
int main()
{
    freopen("contest.in","r",stdin);
    freopen("contest.out","w",stdout);
    m=read()+1,n=read();
    for(int i=1;i<=n;i++)
    {
        r[i].w=read(),r[i].id=i; int x=read();
        for(int j=1;j<=x;j++) e[i][read()]=true;
    }
    sort(r+1,r+n+1,cmpW);
    for(int i=1;i<=n;i++) w[i]=r[i].w,map[r[i].id]=i;
    for(int u=1;u<=n;u++)
        for(int v=1;v<=n;v++) if(e[u][v]) ed[map[u]][map[v]]=true;
    int L=1,R=n;
    while(L<=R)
    {
        int mid=L+R>>1;
        if(check(mid)) L=mid+1;
        else R=mid-1;
    }
    if(R<n) printf("%d\n",r[R+1].w);
    else puts("AK");
    return 0;
}

D1T3

//party
#include <cstdio>
#include <cstring>
inline int max(int x,int y) {return x>y?x:y;}
const int S=1<<16;
const int P=1e9+7;
int n,m,U; char s0[20];
int tr1[S][3],tr2[3][3];
int f1[20],f2[20];
int getDP(int x)
{
    for(int i=1;i<=m;i++)
        f2[i]=max(f1[i-1]+(x==s0[i]),max(f1[i],f2[i-1]));
    int s=0;
    for(int i=1;i<=m;i++) s|=(f2[i]-f2[i-1])<<i-1;
    return s;
}
int dp[2][S][4];
int bitcnt(int s) {int r=0; while(s) r+=s&1,s>>=1; return r;}
int ans[20];
int main()
{
    freopen("party.in","r",stdin);
    freopen("party.out","w",stdout);
    scanf("%d%d",&n,&m); scanf("%s",s0+1);
    for(int i=1;i<=m;i++)
        if(s0[i]=='N') s0[i]=0;
        else if(s0[i]=='O') s0[i]=1;
        else s0[i]=2;
    U=(1<<m)-1;
    for(int s=0;s<=U;s++)
    {
        for(int i=1;i<=m;i++) f1[i]=f1[i-1]+((s>>i-1)&1);
        for(int k=0;k<3;k++) tr1[s][k]=getDP(k);
    }
    tr2[0][0]=1;
    tr2[1][0]=1,tr2[1][1]=2;
    tr2[2][0]=1,tr2[2][2]=3;
    int c=0; dp[c][0][0]=1;
    for(int i=1;i<=n;i++)
    {
        c^=1;
        for(int s1=0;s1<=U;s1++)
            for(int s2=0;s2<3;s2++)
                for(int k=0;k<3;k++)
                    dp[c][tr1[s1][k]][tr2[s2][k]]+=dp[c^1][s1][s2],dp[c][tr1[s1][k]][tr2[s2][k]]%=P;
        memset(dp[c^1],0,sizeof dp[c^1]);
    }
    for(int s=0;s<=U;s++) ans[bitcnt(s)]=((long long)ans[bitcnt(s)]+dp[c][s][0]+dp[c][s][1]+dp[c][s][2])%P;
    for(int i=0;i<=m;i++) printf("%d\n",ans[i]);
    return 0;
}

D2T1

//str
#include <cstdio>
#include <cstring>
const int N=1e4+10;
const int P=1e9+7;
int n,k; char s[N],s0[30];
int f[2][N];
int nxt[30];
void getNxt(char s[])
{
    int len=strlen(s+1);
    nxt[0]=nxt[1]=0;
    for(int i=2;i<=len;i++)
    {
        int j=nxt[i-1];
        while(j&&s[i]!=s[j+1]) j=nxt[j];
        if(s[i]==s[j+1]) nxt[i]=j+1;
        else nxt[i]=0;
    }
}
int main()
{
    freopen("str.in","r",stdin);
    freopen("str.out","w",stdout);
    scanf("%d",&k);
    scanf("%s",s+1),n=strlen(s+1);
    int c=0;
    for(int i=0;i<=n;i++) f[c][i]=1;
    for(int owo=0;owo<k;owo++,c^=1)
    {
        memset(f[c^1],0,sizeof f[c^1]);
        int cnt; scanf("%d",&cnt);
        while(cnt--)
        {
            scanf("%s",s0+1); getNxt(s0);
            int len=strlen(s0+1);
            for(int i=1,j=0;i<=n;i++)
            {
                while(j&&s[i]!=s0[j+1]) j=nxt[j];
                if(s[i]==s0[j+1]) j++;
                if(j==len) f[c^1][i]=(f[c^1][i]+f[c][i-len])%P;
            }
        }
    }
    int ans=0;
    for(int i=0;i<=n;i++) ans=(ans+f[c][i])%P;
    printf("%d\n",ans);
    return 0;
}

D2T2

//xor
#include <algorithm>
#include <cstdio>
using namespace std;
inline char gc()
{
    static char now[1<<16],*s,*t;
    if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;}
    return *s++;
}
inline int read()
{
    int x=0; char ch=gc();
    while(ch<'0'||'9'<ch) ch=gc();
    while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x;
}
const int N=1e5+10;
int n,w[N];
int edCnt,h[N];
struct edge{int v,nxt;} ed[N<<1];
void edAdd(int u,int v)
{
    edCnt++; ed[edCnt].v=v,ed[edCnt].nxt=h[u],h[u]=edCnt;
    edCnt++; ed[edCnt].v=u,ed[edCnt].nxt=h[v],h[v]=edCnt;
}
int fa[N][20],dpt[N];
int dfCnt,dfn[N],fr[N],to[N];
void dfs(int u)
{
    dfn[++dfCnt]=u; fr[u]=dfCnt;
    for(int k=1;k<=17;k++) fa[u][k]=fa[fa[u][k-1]][k-1];
    for(int i=h[u];i;i=ed[i].nxt)
    {
        int v=ed[i].v;
        if(v==fa[u][0]) continue;
        fa[v][0]=u,dpt[v]=dpt[u]+1,dfs(v);
    }
    to[u]=dfCnt;
}
inline lca(int u,int v)
{
    if(dpt[u]<dpt[v]) swap(u,v);
    for(int k=17;k>=0;k--) if(dpt[fa[u][k]]>=dpt[v]) u=fa[u][k];
    if(u==v) return u;
    for(int k=17;k>=0;k--) if(fa[u][k]!=fa[v][k]) u=fa[u][k],v=fa[v][k];
    return fa[u][0];
}
const int N1=N*31;
int rt1[N],rt2[N];
int ndCnt,ch[N1][2],siz[N1];
inline void ndCopy(int p,int &q) {ch[p][0]=ch[q][0],ch[p][1]=ch[q][1],siz[p]=siz[q];}
void ins(int &p,int x,int d)
{
    ndCopy(++ndCnt,p);
    p=ndCnt; siz[p]++; 
    if(d<0) return;
    int t=(x>>d)&1;
    ins(ch[p][t],x,d-1);
}
void bldTr2(int u)
{
    ins(rt2[u]=rt2[fa[u][0]],w[u],30);
    for(int i=h[u];i;i=ed[i].nxt)
    {
        int v=ed[i].v;
        if(v!=fa[u][0]) bldTr2(v);
    }
}
int qres;
void query1(int p1,int p2,int x)
{
    int now=0;
    for(int d=30;d>=0;d--)
    {
        int t=((x>>d)&1)^1,sizT=siz[ch[p2][t]]-siz[ch[p1][t]];
        if(!sizT) t^=1;
        p1=ch[p1][t],p2=ch[p2][t],now|=t<<d;
    }
    qres=x^now;
}
void query2(int p1,int p2,int p3,int x)
{
    int now=0;
    for(int d=30;d>=0;d--)
    {
        int t=((x>>d)&1)^1,sizT=siz[ch[p1][t]]+siz[ch[p2][t]]-siz[ch[p3][t]]*2;
        if(!sizT) t^=1;
        p1=ch[p1][t],p2=ch[p2][t],p3=ch[p3][t],now|=t<<d;
    }
    qres=x^now;
}

void show(int p)
{
    if(!p) return;
    printf("%2d siz=%d ch=%d,%d\n",p,siz[p],ch[p][0],ch[p][1]);
    show(ch[p][0]); show(ch[p][1]);
}

int main()
{
    freopen("xor.in","r",stdin);
    freopen("xor.out","w",stdout);
    n=read(); int Q=read();
    for(int i=1;i<=n;i++) w[i]=read();
    for(int i=1;i<=n-1;i++)
    {
        int u=read(),v=read();
        edAdd(u,v);
    }
    fa[1][0]=0,dpt[1]=1,dfs(1);
    for(int i=1;i<=n;i++) ins(rt1[i]=rt1[i-1],w[dfn[i]],30);
    bldTr2(1);
    /*for(int i=1;i<=n;i++) show(rt1[i]),puts("");
    puts("");
    for(int i=1;i<=n;i++) show(rt2[i]),puts("");*/

    while(Q--)
    {
        int opt=read();
        if(opt==1)
        {
            int u=read(),x=read();
            qres=0; query1(rt1[fr[u]-1],rt1[to[u]],x);
        }
        else
        {
            int u=read(),v=read(),x=read();
            int t=lca(u,v);
            qres=0; query2(rt2[u],rt2[v],rt2[t],x);
            qres=max(qres,w[t]^x);
        }
        printf("%d\n",qres);
    }
    return 0;
}

D2T3

//教科书般的亵渎
#include <algorithm>
#include <cstdio>
using std::sort;
typedef long long lint;
inline lint read()
{
    lint x=0; char ch=getchar();
    while(ch<'0'||'9'<ch) ch=getchar();
    while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x;
}
const int P=1e9+7;
const int M=60;
lint n,a[M]; int m;
int B[M],C[M][M],inv[M];
void init(int n)
{
    inv[1]=1;
    for(int i=2;i<=n;i++) inv[i]=1LL*inv[P%i]*(P-P/i)%P;
    for(int i=0;i<=n;i++)
    {
        C[i][0]=1;
        for(int j=1;j<=i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%P;
    }
    B[0]=1;
    for(int i=1;i<=n-1;i++)
    {
        B[i]=0;
        for(int j=0;j<=i-1;j++) B[i]=(B[i]+1LL*C[i+1][j]*B[j])%P;
        B[i]=(1LL*(P-B[i])*inv[i+1])%P;
    }
}
int pow(lint x,int y)
{
    lint r=1,t=x;
    for(int i=y;i;i>>=1,t=t*t%P) if(i&1) r=r*t%P;
    return r;
}
int S(lint n)
{
    int s=0;
    for(int i=1;i<=m+1;i++) s=(s+1LL*C[m+1][i]*B[m+1-i]%P*pow(n+1,i)%P)%P;
    s=1LL*s*inv[m+1]%P;
    //printf("Sigma(%d,%d)=%d\n",n,m,s);
    return s;
}
int main()
{
    freopen("defile.in","r",stdin);
    freopen("defile.out","w",stdout);
    init(59);
    int task=read();
    while(task--)
    {

    n=read(),m=read();
    for(int i=1;i<=m;i++) a[i]=read();
    a[++m]=++n; sort(a+1,a+m+1);
    lint ans=0;
    for(int i=1;i<=m;i++)
    {
        for(int j=i;j<=m;j++) ans=(ans+S(a[j]-1)-S(a[j-1])+P)%P;
        for(int j=i+1;j<=m;j++) a[j]-=a[i]; a[i]=0;
    }
    printf("%lld\n",ans);

    }
    return 0;
}

转载于:https://www.cnblogs.com/VisJiao/p/8988878.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值