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; }
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; }
不想退役就静下来