JXOI2018簡要題解

T1排序問題

考慮若是全部數都不一樣,那麼必定只有一種方案可行,須要\(n!\)

若是有數相同,考慮強制大小關係,最後除上每一個相同數以內的排列個數

考慮如何加入新的數,明顯是越平均越好,模擬一下便可

複雜度爲\(O(Tn \log n)\)

#include <bits/stdc++.h>
#define N 200005
#define M 10000005
#define mod 998244353
#define getchar nc
using namespace std;
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()
{
    register int x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*f;
}
inline void write(register int x)
{
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[20];register int tot=0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
inline int power(register int a,register int b)
{
    int res=1;
    while(b)
    {
        if(b&1)
            res=1ll*res*a%mod;
        a=1ll*a*a%mod;
        b>>=1;
    }
    return res;
}
int fac[N+M];
int T,n,m,l,r,ans,a[N],b[N],c[N],t[N];
inline void solve()
{
    n=read(),m=read(),l=read(),r=read();
    for(register int i=1;i<=n;++i)
        a[i]=read();
    ans=fac[n+m];
    int t1=0,t2=0,top=0;
    sort(a+1,a+1+n);
    for(register int i=1;i<=n;++i)
        if(l<=a[i]&&a[i]<=r)
            b[++t1]=a[i];
        else
            c[++t2]=a[i];
    b[t1+1]=c[t2+1]=0;
    for(register int i=2,res=1;i<=t2+1;++i)
        if(c[i]!=c[i-1])
            ans=1ll*ans*power(fac[res],mod-2)%mod,res=1;
        else
            ++res;
    for(register int i=2,res=1;i<=t1+1;++i)
        if(b[i]!=b[i-1])
            t[++top]=res,res=1;
        else
            ++res;
    sort(t+1,t+top+1);
    int lef=r-l+1-top,nw=0,i=1;
    for(;i<=top;++i)
    {
        if(1ll*lef*(t[i]-nw)<=m)
            m-=1ll*lef*(t[i]-nw),nw=t[i],++lef;
        else 
            break;
    }
    nw+=m/lef;
    m%=lef;
    ans=1ll*ans*power(power(fac[nw],mod-2),lef-m)%mod;
    ans=1ll*ans*power(power(fac[nw+1],mod-2),m)%mod;
    for(;i<=top;++i)
        ans=1ll*ans*power(fac[t[i]],mod-2)%mod;
    write(ans),puts("");
}
int main()
{
    fac[0]=1;
    for(register int i=1;i<N+M;++i)
        fac[i]=1ll*fac[i-1]*i%mod;
    T=read();
    while(T--)
        solve();
    return 0;
}

T2遊戲

根據倍數關係珂以建出圖,舉個栗子:1,2,3要向6連邊,1,2,4要向8連邊……,這個珂以線性篩解決

這樣咱們珂以得出結論,要把全部度數爲0的點選上,設這個數爲\(k\),則

\[Ans=\sum_{i=k}^n i \tbinom{i-1}{k-1} k! (n-k)!\]c++

\(\tbinom{i-1}{k-1}\)表示第\(i\)個取的點是度數爲0的點,前面\(i-1\)個取的點要有\(k-1\)個度數爲0的點的方案數,\(k!\)\((n-k)!\)表示度數是否爲0的以內的排序方案數

暴力計算一下便可,複雜度爲\(O(n)\)

#include <bits/stdc++.h>
#define N 10000005
#define mod 1000000007
#define getchar nc
using namespace std;
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()
{
    register int x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*f;
}
inline void write(register int x)
{
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[20];register int tot=0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
inline int power(register int a,register int b)
{
    int res=1;
    while(b)
    {
        if(b&1)
            res=1ll*res*a%mod;
        a=1ll*a*a%mod;
        b>>=1;
    }
    return res;
}
int l,r,n,ans,cnt;
int ispr[N],pr[N],tot,fac[N],invf[N];
inline void init()
{
    ispr[1]=pr[1]=1;
    if(l==1)
    {
        cnt=1;
        return;
    }
    for(register int i=2;i<=r;++i)
    {
        if(!ispr[i])
            pr[++tot]=i,cnt+=(i>=l);
        for(register int j=1;j<=tot&&pr[j]*i<=r;++j)
        {
            ispr[pr[j]*i]=1;
            if(i<l&&i*pr[j]>=l)
                ++cnt;
            if(i%pr[j]==0)
                break;
        }
    }
}
int main()
{
    l=read(),r=read(),n=r-l+1;
    init();
    fac[0]=1;
    for(register int i=1;i<=n;++i)
        fac[i]=1ll*fac[i-1]*i%mod;
    invf[n]=power(fac[n],mod-2);
    for(register int i=n-1;i>=0;--i)
        invf[i]=1ll*invf[i+1]*(i+1)%mod;
    for(register int i=cnt;i<=n;++i)
        ans=(0ll+ans+1ll*i*fac[i-1]%mod*invf[i-cnt]%mod)%mod;
    write(1ll*ans*invf[cnt-1]%mod*fac[cnt]%mod*fac[n-cnt]%mod);
    return 0;
}

T3守衛

挺神奇的一道題,估計考場上就要因這題而200pts退役了

\(f[l][r]\)表示\([l,r]\)的答案,隨便轉移轉移(看了程序就能懂了),複雜度爲\(O(n^2)\)

#include <bits/stdc++.h>
#define N 5005
#define getchar nc
using namespace std;
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()
{
    register int x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*f;
}
inline void write(register int x)
{
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[20];register int tot=0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
int n,h[N],see[N][N],f[N][N],ans;
int main()
{
    n=read();
    for(register int i=1;i<=n;++i)
        h[i]=read();
    for(register int i=1,l=0;i<=n;++i,l=i-1)
        for(double mx=1e9;l>=1;--l)
            if(1.0*(h[i]-h[l])/(i-l)<mx)
                mx=1.0*(h[i]-h[l])/(i-l),see[l][i]=1;
    for(register int r=1;r<=n;++r)
        for(register int l=r,s=1,las=l;l>=1;--l)
        {
            if(see[l][r])
            {
                if(!see[l+1][r])
                    s+=min(f[l+1][las],f[l+1][las+1]);
                f[l][r]=s;
            }
            else
            {
                if(see[l+1][r])
                    las=l;
                f[l][r]=s+min(f[l][las],f[l][las+1]);
            }
            ans^=f[l][r];
        }
    write(ans);
    return 0;
}
相關文章
相關標籤/搜索