10.1 csp-s模拟测试(b) X国的军队+排列组合+回文

T1 X国的军队

贪心,按$b-a$的大小降序排序,然后就贪心吧

#include
#include
#include
#define ll long long
using namespace std;
struct node
{
    ll a,b,las;
}h[100100];
ll T,n,ans;
ll read()
{
    ll aa=0,bb=1;char cc=getchar();
    while(cc>'9'||cc<'0'){if(cc=='-') bb=-1;cc=getchar();}
    while(cc<='9'&&cc>='0'){aa=aa*10+cc-'0';cc=getchar();}
    return aa*bb;
}
bool cmp(node x,node y)
{
    return x.b-x.a>y.b-y.a;
}
int main()
{
    T=read();
    while(T--){
        n=read();ans=0;
        for(int i=1;i<=n;i++) h[i].a=read(),h[i].b=read();
        sort(h+1,h+n+1,cmp);
        for(int i=1;i<=n;i++){
            if(h[i-1].las<=h[i].b) ans+=h[i].b-h[i-1].las,h[i].las=h[i].b-h[i].a;
            else h[i].las=h[i-1].las-h[i].b+h[i].b-h[i].a;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
X国的军队

 

 

T2 排列组合

结论:$\sum{C_n^i*C_n^i}=C_{2*n}^n$

$\sum{C_n^i*C_n^i}=\sum{C_n^i*C_n^(n-i)}$

考虑他的意义,在n个物品中选$i$个,再从$n$个物品中选$n-i$个

也就是$2*n$个物品,从前$n$个中选$i$个,从后$n$个中选$n-i$个

因为$i\in(0,n)$,取遍了所有的数,所以就是$C_{2*n}^n$

就是在$2*n$的序列中,任选$n$个,有i个在左半边,那么就一定有$n-i$个在右半边,两者是一一对应的

#include
#include
#define ll long long
#define mod 1000000007
using namespace std;
ll T,n,ans,fac[2001000],facinv[2001000],inv[2001000];
ll read()
{
    ll aa=0,bb=1;char cc=getchar();
    while(cc>'9'||cc<'0'){if(cc=='-') bb=-1;cc=getchar();}
    while(cc<='9'&&cc>='0'){aa=aa*10+cc-'0';cc=getchar();}
    return aa*bb;
}
void init()
{
    fac[0]=1;inv[1]=1;facinv[0]=1;
    for(ll i=1;i<=2000000;i++){
        if(i!=1) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
        fac[i]=fac[i-1]*i%mod;
        facinv[i]=facinv[i-1]*inv[i]%mod;
    }
}
ll C(ll x,ll y)
{
    return fac[x]*facinv[y]%mod*facinv[x-y]%mod;
}
int main()
{
    T=read();init();
    while(T--) n=read(),printf("%lld\n",C(n+n,n));
    return 0;
}
排列组合

 

 

T3 回文

我只会暴力,我不会马拉车的部分分

$g[i][j]$表示从$i$到$j$是否是回文串,转移很简单,$g[i][j]=1$ $(s[i]==s[j]$&&$g[i+1][j-1]==1)$,边界要特判一下,一个奇数边界,一个偶数边界

$f[i][j]$表示$i$到$j$中一共有多少个回文串,转移稍用容斥,$f[i][j]=f[i+1][j]+f[i][j-1]-f[i+1][j-1]+g[i][j]$,这个边界其实没有判的必要

#include
#include
#include
using namespace std;
int n,m,f[5010][5010];
char s[5010];
bool g[5010][5010];
int read()
{
    int aa=0,bb=1;char cc=getchar();
    while(cc>'9'||cc<'0'){if(cc=='-') bb=-1;cc=getchar();}
    while(cc<='9'&&cc>='0'){aa=(aa<<3)+(aa<<1)+(cc^'0');cc=getchar();}
    return aa*bb;
}
int main()
{
    scanf("%s",s+1);n=strlen(s+1);
    for(int i=n;i>=1;i--){
        g[i][i]=1;
        if(s[i]==s[i+1]) g[i][i+1]=1;
        for(int j=i+2;j<=n;j++) if(s[i]==s[j]&&g[i+1][j-1]) g[i][j]=1;
    }
    for(int i=n;i>=1;i--)
        for(int j=i;j<=n;j++)
            f[i][j]=f[i+1][j]+f[i][j-1]-f[i+1][j-1]+g[i][j];
    m=read();int l,r;
    for(int i=1;i<=m;i++) l=read(),r=read(),printf("%d\n",f[l][r]);
    return 0;
}
回文

 

 

不想退役就静下来

你可能感兴趣的:(10.1 csp-s模拟测试(b) X国的军队+排列组合+回文)