Codeforces Round #313 (Div. 2)

下午打了一场CF,感觉挺简单的于是边颓废边做,结果差点没调出最后一题知道01:59才做完。。。

A. Currency System in Geraldion

min(ai)=1 ,则 ans=1 ,否则 ans=1

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define ll long long 
using namespace std;
int n,a[1005];
inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
int main()
{
    n=read();
    for (int i=1;i<=n;i++) a[i]=read();
    sort(a+1,a+n+1);
    if (a[1]!=1) puts("1"); else puts("-1");
    return 0;
}

B. Gerald is into Art

判断每一种情况。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define ll long long 
using namespace std;
int a1,a2,a3,b1,b2,b3;
inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
inline bool judge()
{
    if (a2+a3<=a1&&b2<=b1&&b3<=b1) return 1;
    if (a2+a3<=b1&&b2<=a1&&b3<=a1) return 1;
    if (b2+b3<=b1&&a2<=a1&&a3<=a1) return 1;
    if (b2+b3<=a1&&a2<=b1&&a3<=b1) return 1;
    if (a2+b3<=a1&&b2<=b1&&a3<=b1) return 1;
    if (a2+b3<=b1&&b2<=a1&&a3<=a1) return 1;
    if (b2+a3<=a1&&a2<=b1&&b3<=b1) return 1;
    if (b2+a3<=b1&&a2<=a1&&b3<=a1) return 1;
    return 0;
}
int main()
{
    a1=read(); b1=read(); a2=read(); b2=read(); a3=read(); b3=read();
    judge()?puts("YES"):puts("NO");
    return 0;
}

C. Gerald’s Hexagon

可以发现边长为 x 的正三角形存在x2个小三角形,我们可以补齐这个三角形,再减去多余的部分。设三条相邻边为 x,y,z ,则

ans=(x+y+z)2x2y2z2=2(xy+yz+xz)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define ll long long 
using namespace std;
int a[10];
inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
int main()
{
    for (int i=1;i<=6;i++) a[i]=read();
    printf("%d",(a[1]+a[2]+a[3])*(a[1]+a[2]+a[3])-a[1]*a[1]-a[5]*a[5]-a[3]*a[3]);
    return 0;
}

D. Equivalent Strings

题意把作法说的很清楚了,直接分治。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define ll long long 
using namespace std;
char A[200005],B[200005];
int n;
bool judge(int l1,int r1,int l2,int r2)
{
    bool flag=1;
    for (int i=l1;i<=r1;i++) 
        if (A[i]!=B[i+l2-l1]) {flag=0; break;}
    if (flag) return 1;
    int len=r1-l1+1;
    if (len&1) return 0;
    int mid1=l1+r1>>1,mid2=l2+r2>>1;
    if (judge(l1,mid1,l2,mid2)&&judge(mid1+1,r1,mid2+1,r2)) return 1;
    if (judge(l1,mid1,mid2+1,r2)&&judge(mid1+1,r1,l2,mid2)) return 1;
    return 0;
}
int main()
{
    scanf("%s",A+1);
    scanf("%s",B+1);
    if (strlen(A+1)!=strlen(B+1)) {puts("NO"); return 0;}
    n=strlen(A+1);
    if (judge(1,n,1,n)) puts("YES"); else puts("NO");
    return 0;
}

E. Gerald and Giant Chess

O(k2) 的dp。
我们考虑点 i(xi,yi),j(xj,yj) ,满足 xi<=xj,yi<=yj xi=xj,yi=yj 不同时成立,这两点之间的不同路径的方案数,记为 calc(xi,yi,xj,yj)
我们令 x=xjxi,y=yjyi
那么显然我们要水平走 x 步,竖直走y步,相当于向长度为 x+y 的操作序列中选 x 个位置填数,所以calc(xi,yi,xj,yj)=Cxx+y
然后我们对点按照坐标排序(注意要将左上角点 (1,1) 和右下角点 (n,m) 加入),令 dpi 表示当前在第i个点的答案。

dpi=calc(1,1,xi,yi)j=1i1dpjcalc(xj,yj,xi,yi)

然后就可以跑dp啦,求组合数的时候用Lucas定理,注意此题要开long long。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define ll long long 
#define P 1000000007

using namespace std;
ll n,m,k,dp[2005],fac[10000005];
struct node {ll x,y;} e[2005];
inline ll read()
{
    ll a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
inline bool cmp(node a,node b)
{
    return a.x==b.x?a.y<b.y:a.x<b.x;
}
ll quick_power(ll a,ll b)
{
    ll ans=1; a%=P;
    for (ll i=b;i;i>>=1,a=a*a%P)
        if (i&1) ans=ans*a%P;
    return ans;
}
ll C(ll n,ll m)
{
    return fac[n]*quick_power(fac[m]*fac[n-m],P-2)%P;
}

ll lucas(ll n,ll m)
{
    if (n<m) return 0;
    if (n<P&&m<P) return C(n,m);
    return lucas(n/P,m/P)*lucas(n%P,m%P)%P;
}
ll calc(ll x1,ll y1,ll x2,ll y2)
{
    if (x1>x2||y1>y2) return 0;
    ll x=x2-x1,y=y2-y1;
    return lucas(x+y,x);
}
int main()
{
    fac[0]=1;
    for (int i=1;i<=10000000;i++) fac[i]=fac[i-1]*i%P;
    n=read(); m=read(); k=read();
    for (int i=1;i<=k;i++) 
        e[i].x=read(),e[i].y=read();
    e[++k].x=e[k].y=1; e[++k].x=n; e[k].y=m;
    sort(e+1,e+k+1,cmp);
    for (int i=2;i<=k;i++)
    {
        dp[i]=calc(1,1,e[i].x,e[i].y);
        for (int j=1;j<i;j++)
            dp[i]=(dp[i]-(dp[j]*calc(e[j].x,e[j].y,e[i].x,e[i].y)%P)+P)%P;
    }
    cout << dp[k];
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值