题目: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=(6∗n−3)∗Sn−1−(n−2)∗Sn−2,第i项的施罗德数(超级卡特兰数)为
S
i
−
1
∗
2
S_{i-1}*2
Si−1∗2(第一项除外)。
(证明推导目前不会)
第一个式子可以形象理解为从(0,0)至(n,n)只能往右,上,右上,从0–n-1-k的方案数乘以0–k的方案数, S n − 1 S_{n-1} Sn−1即为走斜线的时候。
上述题目便可以解决了。
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;
}
};