(天池)超级码力在线编程大赛初赛 第2场

题目:click

1.三角魔法
在这里插入图片描述

叉乘判断。注意三点构不成三角形的坐标情况,应该是要非退化三角形。(粘个板子)

typedef long long ll;
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f

class Solution {
public:
    struct Point {
        ll x,y;
    };
    ll solve(Point p1,Point p2,Point p3) {
        return ((p1.x-p2.x)*(p3.y-p2.y)-(p1.y-p2.y)*(p3.x-p2.x));
    }
    string castMagic(vector<vector <int > > &triangle, vector<int> &point) {
        Point P,A,B,C;
        P.x=point[0];
        P.y=point[1];
        A.x=triangle[0][0],A.y=triangle[0][1];
        B.x=triangle[1][0],B.y=triangle[1][1];
        C.x=triangle[2][0],C.y=triangle[2][1];
        if(solve(A,B,C)==0) {
            return "No";
        }
        ll ca,ba,cb;
        ca=solve(C,A,P);
        ba=solve(B,A,P);
        if((ca>0&&ba>0)||(ca<0&&ba<0))
                 return "No";
             if(ca==0&&ba==0) return "Yes";
            cb = solve(C, B, P);
             if (cb == 0) return "Yes";
             if (ba == 0)
             {
                 if ((ca > 0 && cb > 0) || (ca < 0 && cb < 0))
                     return "No";
                 else return "Yes";
             }
             if ((ba > 0 && cb > 0) || (ba < 0 && cb < 0))
                 return "Yes";
             else return "No";
    }
};

2.区间异或
在这里插入图片描述
RMQ板子一打,处理出区间的最大最小。直接异或。
貌似分治或者线段树做标记也可以。

typedef long long ll;
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
class Solution {
public:
    int stmax[50010][20];
    int stmin[50010][20];
    void init(vector<int> &a)
    {
        int i,j,k;
        int n=a.size();
        for(i=1;i<=n;i++)
        stmax[i][0]=stmin[i][0]=a[i-1];
        int t=log2(n)+1;
        for(int j=1;j<t;j++)
        {
            for(int i=1;i<=n-(1<<j)+1;i++)
            {
                stmax[i][j]=max(stmax[i][j-1],stmax[i+(1<<(j-1))][j-1]);
                stmin[i][j]=min(stmin[i][j-1],stmin[i+(1<<(j-1))][j-1]);
            }
        }
    }
    int solvemax(int l,int r)
    {
        int k=log2(r-l+1);
        return max(stmax[l][k],stmax[r-(1<<k)+1][k]);
    }
    int solvemin(int l,int r)
    {
        int k=log2(r-l+1);
        return min(stmin[l][k],stmin[r-(1<<k)+1][k]);
    }
    int Intervalxor(vector<int> &num, vector<vector<int>> &ask) {
        init(num);
        int ans=0;
        for(int i=0;i<ask.size();++i) {
            int hh1=solvemax(ask[i][0],ask[i][1]);
            int hh2=solvemin(ask[i][2],ask[i][3]);
            ans^=(hh1+hh2);
        }
        return ans;
    }
};

3.五字回文

在这里插入图片描述
直接暴力,但是需要判断一下是三个不同的字符组成的长度为5的回文串。

class Solution {
public:
    int Fivecharacterpalindrome(string &s) {
        int sum=0;
        for(int i=0;i<s.length();++i) {
            int j=i+4;
            if(j>=s.length())
                break;
            if(s[i]==s[j]&&s[i+1]==s[j-1]&&s[i]!=s[i+1]&&s[i]!=s[j-2]&&s[i+1]!=s[j-2]){
                sum++;
            }
        }
        return sum;
    }
};

4.小栖的金字塔

在这里插入图片描述
施罗德数(超级卡特兰数),施罗德数是一组可用于解决组合数学中某些问题的序列。
在组合数学中,施罗德数用来描述从(0,0)到(n,n)的格路中,只能使用(1,0)、(0,1)、(1,1)三种移动方式,始终位于对角线下方且不越过对角线的路径数。
施罗德数的前几项为1, 2, 6, 22, 90, 394, 1806, 8558, 41586, 206098,…

在这里插入图片描述
递推:
( n + 1 ) ∗ S n = ( 6 ∗ n − 3 ) ∗ S n − 1 − ( n − 2 ) ∗ S n − 2 (n+1)*S_n=(6*n-3)*S_{n-1}-(n-2)*S_{n-2} (n+1)Sn=(6n3)Sn1(n2)Sn2,第i项的施罗德数(超级卡特兰数)为 S i − 1 ∗ 2 S_{i-1}*2 Si12(第一项除外)。
(证明推导目前不会)

第一个式子可以形象理解为从(0,0)至(n,n)只能往右,上,右上,从0–n-1-k的方案数乘以0–k的方案数, S n − 1 S_{n-1} Sn1即为走斜线的时候。

上述题目便可以解决了。

typedef long long ll;
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
class Solution {
public:
    const ll mod=1e9+7;
    /**
     * @param n: The number of pyramid levels n
     * @param k: Possible coordinates k
     * @return: Find the sum of the number of plans
     */
     ll num[10000010];
    ll quickpow(ll a,ll n) {
        ll res=1;
        while(n) {
            if(n&1) {
                res=(res*a)%mod;
            }
            n>>=1;
            a=(a*a)%mod;
        }
        return res%mod;
    }
    int pyramid(int n, vector<int> &k) {
        num[1]=num[0]=1;
        for(ll i=2;i<=n;++i) {
            num[i]=((6*i-3)*num[i-1]%mod-(i-2)*num[i-2]%mod+mod)%mod*quickpow(i+1,mod-2)%mod;
        }
        ll ans=0;
        for(int i=0;i<k.size();++i) {
            if(k[i]==n||n==1) {
                 ans=(ans+1)%mod;
                 continue;
            }
            ans=(ans+(num[n-k[i]]*2)%mod)%mod;
        }
        return (int)ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值