这场6题,不过罚时有点炸,不符合我们的队以往的作风。。剩下的题有点算法有点涉及到我们的盲区了...继续努力把~
1 Frog
————————————————————————————————————
水2 Triangles
————————————————————————————————————
给你两个三角形,问你这两个三角形是包含的,还是相交的,还是相离的。
其实是一个jianda
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
const double eps = 1e-6;
int sgn(double x)
{
if(fabs(x) < eps)return 0;
if(x < 0)return -1;
else return 1;
}
struct Point
{
double x,y;
Point(){}
Point(double _x,double _y)
{
x = _x;y = _y;
}
Point operator -(const Point &b)const
{
return Point(x - b.x,y - b.y);
}
double operator ^(const Point &b)const
{
return x*b.y - y*b.x;
}
double operator *(const Point &b)const
{
return x*b.x + y*b.y;
}
void transXY(double B)
{
double tx = x,ty = y;
x = tx*cos(B) - ty*sin(B);
y = tx*sin(B) + ty*cos(B);
}
};
struct Line
{
Point s,e;
Line(){}
Line(Point _s,Point _e)
{
s = _s;e = _e;
}
pair<int,Point> operator &(const Line &b)const
{
Point res = s;
if(sgn((s-e)^(b.s-b.e)) == 0)
{
if(sgn((s-b.e)^(b.s-b.e)) == 0)
return make_pair(0,res);
else return make_pair(1,res);
}
double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
res.x += (e.x-s.x)*t;
res.y += (e.y-s.y)*t;
return make_pair(2,res);
}
};
bool inter(Line l1,Line l2)
{
return
max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0 &&
sgn((l1.s-l2.e)^(l2.s-l2.e))*sgn((l1.e-l2.e)^(l2.s-l2.e)) <= 0;
}
bool OnSeg(Point P,Line L)
{
return
sgn((L.s-P)^(L.e-P)) == 0 &&
sgn((P.x - L.s.x) * (P.x - L.e.x)) <= 0 &&
sgn((P.y - L.s.y) * (P.y - L.e.y)) <= 0;
}
int inConvexPoly(Point a,Point p[],int n)
{
for(int i = 0;i < n;i++)
{
if(sgn((p[i]-a)^(p[(i+1)%n]-a)) < 0)return -1;
else if(OnSeg(a,Line(p[i],p[(i+1)%n])))return 0;
}
return 1;
}
int inPoly(Point p,Point poly[],int n)
{
int cnt;
Line ray,side;
cnt = 0;
ray.s = p;
ray.e.y = p.y;
ray.e.x = -100000000000.0;
for(int i = 0;i < n;i++)
{
side.s = poly[i];
side.e = poly[(i+1)%n];
if(OnSeg(p,side))return 0;
//如果平行轴则不考虑
if(sgn(side.s.y - side.e.y) == 0)
continue;
if(OnSeg(side.s,ray))
{
if(sgn(side.s.y - side.e.y) > 0)cnt++;
}
else if(OnSeg(side.e,ray))
{
if(sgn(side.e.y - side.s.y) > 0)cnt++;
}
else if(inter(ray,side))
cnt++;
}
if(cnt % 2 == 1)return 1;
else return -1;
}
int main()
{
int t;
cin >> t;
int x1, x2, x3, x4, x5, x6, y1,y2,y3,y4,y5,y6;
while(t--)
{
scanf("%d%d%d%d%d%d", &x1, &y1, &x2, &y2, &x3, &y3);
scanf("%d%d%d%d%d%d", &x4, &y4, &x5, &y5, &x6, &y6);
Point p1[10], p2[10];
// if(x1 > x2) swap(x1, x2);
// if(y1 > y2) swap(y1, y2);
// if(x1 > x3) swap(x1, x3);
// if(y1 > y3) swap(y1, y3);
// if(x2 > x3) swap(x2, x3);
// if(y2 > y3) swap(y2, y3);
p1[0] = Point(x1, y1);
p1[1] = Point(x2, y2);
p1[2] = Point(x3, y3);
// if(x4 > x5) swap(x4, x5);
// if(y4 > y5) swap(y4, y5);
// if(x4 > x6) swap(x4, x6);
// if(y4 > y6) swap(y4, y6);
// if(x5 > x6) swap(x5, x6);
// if(y5 > y6) swap(y5, y6);
p2[0] = Point(x4, y4);
p2[1] = Point(x5, y5);
p2[2] = Point(x6, y6);
int flag = 0;
if(inPoly(p1[0], p2, 3) == 1 && inPoly(p1[1], p2, 3) == 1 && inPoly(p1[2], p2, 3) == 1)
flag = 1;
if(inPoly(p2[0], p1, 3) == 1 && inPoly(p2[1], p1, 3) == 1 && inPoly(p2[2], p1, 3) == 1)
flag = 1;
for(int i = 0; i < 3; i++)
{
for(int j = i; j < 3; j++)
{
Line l1 = Line(p1[i], p1[j]);
for(int x = 0; x < 3; x++)
{
for(int y = x; y < 3; y++)
{
Line l2 = Line(p2[x], p2[y]);
if(inter(l1, l2))
flag = 2;
}
}
}
}
if(flag == 1)
puts("contain");
else if(flag == 2)
puts("intersect");
else
puts("disjoint");
}
return 0;
}
/*
10
4 3 7 3 7 6
5 2 5 10 6 10
*/
3 DotA and LOL
————————————————————————————————————
4 Game
————————————————————————————————————
给你两个大数,(不含前导零),
两个人轮流操作自己的数,可以除以10(向下取整,没有小数.)或者翻转过去,(翻转之后要去掉前导0).
当有一时刻两个数相等则A赢,否则B赢,所以A想要将两个数变得相同,B想讲两个数变得不同.
问你两个人最后谁赢?
可以考虑一下,因为每一轮每人必须要对自己的数进行一次操作,直到最后为0,也一直在进行,一直是0了.
所以我们可以想到,如果当前B不能在A中正着匹配,或者反着匹配,那么无论A怎么变我B就一直翻转我的数,那你永远
也别想赢.否则如果A中有B的子串,那你B无论怎么办,总有一个A==B ,上面也说了即使除到0,最后就真的一直是0
俩人都是0也匹配了.
另外需要注意,如果一开始B后面有0,需要将B中的后缀0 全部去掉,在跟A进行匹配.但是A中后面的0对结果无影响.
举例: 1235 120
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <queue>
#define maxs 2020202
#define mme(i,j) memset(i,j,sizeof(i))
using namespace std;
char s[1000005],s2[1000005];
int nexts[maxs];
void getn()
{
int len=strlen(s2);
int i=0,j;
j=nexts[0]=-1;
for(i=0;i<len;)
{
if(j==-1 || s2[i]==s2[j])
nexts[++i]=++j;
else
j=nexts[j];
}
}
bool kmp()
{
getn();
int len1=strlen(s),len2=strlen(s2);
int i=0,j=0;
for(i=0;i<len1;)
{
if(j==-1||s[i]==s2[j])
{
i++;
j++;
}
else
j=nexts[j];
if(j>=len2)
return 1;
}
if(j>=len2)
return 1;
return 0;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s%s",s,s2);
int flag = 1;
for(int i=0;s2[i];i++){
if(s2[i]=='0') continue;
flag = 0 ;break;
}
int l2 = strlen(s2);
for(int i=l2-1;i>=0;i--){
if(s2[i]=='0')
s2[i]='\0';
else break;
}
// puts(s2);
if(flag||kmp())
{
printf("Alice\n");
}
else
{
reverse(s2,s2+strlen(s2));
if(kmp())
{
printf("Alice\n");
}
else printf("Bob\n");
}
}
}
5 Doctor
————————————————————————————————————
6 Change
————————————————————————————————————
7 YYS
————————————————————————————————————
就是有一个人,要集齐n张卡,每个卡出现的概率都为1/n,他每隔w天可以买一次卡,问你集齐所有卡片的期望是多少.
主要是数太大了- -,最后化简是 n!/i, i 从1 到 n, 找了一大堆大数模板,最后才找到一个不错的,概率dp+大数把
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <stack>
#include <cstring>
using namespace std;
//const int maxn = 1e6; //大数位数
#define MAXN 9999
#define MAXSIZE 10
#define DLEN 4
class BigNum
{
private:
int a[MAXN]; //可以控制大数的位数
int len; //大数长度
public:
BigNum(){ len = 1;memset(a,0,sizeof(a)); } //构造函数
BigNum(const int); //将一个int类型的变量转化为大数
BigNum(const char*); //将一个字符串类型的变量转化为大数
BigNum(const BigNum &); //拷贝构造函数
BigNum &operator=(const BigNum &); //重载赋值运算符,大数之间进行赋值运算
friend istream& operator>>(istream&, BigNum&); //重载输入运算符
friend ostream& operator<<(ostream&, BigNum&); //重载输出运算符
BigNum operator+(const BigNum &) const; //重载加法运算符,两个大数之间的相加运算
BigNum operator-(const BigNum &) const; //重载减法运算符,两个大数之间的相减运算
BigNum operator*(const BigNum &) const; //重载乘法运算符,两个大数之间的相乘运算
BigNum operator/(const int &) const; //重载除法运算符,大数对一个整数进行相除运算
BigNum operator^(const int &) const; //大数的n次方运算
int operator%(const int &) const; //大数对一个int类型的变量进行取模运算
bool operator>(const BigNum & T)const; //大数和另一个大数的大小比较
bool operator<(const BigNum & T) const;
bool operator==(const BigNum & T) const;
bool operator>(const int & t)const; //大数和一个int类型的变量的大小比较
bool operator<(const int &t) const;
bool operator==(const int &t) const;
void print(); //输出大数
};
bool BigNum::operator==(const BigNum & T) const {
return !(*this > T) && !(T > *this);
}
bool BigNum::operator==(const int &t) const {
BigNum T = BigNum(t);
return *this == T;
}
bool BigNum::operator<(const BigNum & T) const {
return T > *this;
}
bool BigNum::operator<(const int &t) const {
return BigNum(t) > *this;
}
BigNum::BigNum(const int b) //将一个int类型的变量转化为大数
{
int c,d = b;
len = 0;
memset(a,0,sizeof(a));
while(d > MAXN)
{
c = d - (d / (MAXN + 1)) * (MAXN + 1);
d = d / (MAXN + 1);
a[len++] = c;
}
a[len++] = d;
}
BigNum::BigNum(const char*s) //将一个字符串类型的变量转化为大数
{
int t,k,index,l,i;
memset(a,0,sizeof(a));
l=strlen(s);
len=l/DLEN;
if(l%DLEN)
len++;
index=0;
for(i=l-1;i>=0;i-=DLEN)
{
t=0;
k=i-DLEN+1;
if(k<0)
k=0;
for(int j=k;j<=i;j++)
t=t*10+s[j]-'0';
a[index++]=t;
}
}
BigNum::BigNum(const BigNum & T) : len(T.len) //拷贝构造函数
{
int i;
memset(a,0,sizeof(a));
for(i = 0 ; i < len ; i++)
a[i] = T.a[i];
}
BigNum & BigNum::operator=(const BigNum & n) //重载赋值运算符,大数之间进行赋值运算
{
int i;
len = n.len;
memset(a,0,sizeof(a));
for(i = 0 ; i < len ; i++)
a[i] = n.a[i];
return *this;
}
istream& operator>>(istream & in, BigNum & b) //重载输入运算符
{
char ch[MAXSIZE*4];
int i = -1;
in>>ch;
int l=strlen(ch);
int count=0,sum=0;
for(i=l-1;i>=0;)
{
sum = 0;
int t=1;
for(int j=0;j<4&&i>=0;j++,i--,t*=10)
{
sum+=(ch[i]-'0')*t;
}
b.a[count]=sum;
count++;
}
b.len =count++;
return in;
}
ostream& operator<<(ostream& out, BigNum& b) //重载输出运算符
{
int i;
cout << b.a[b.len - 1];
for(i = b.len - 2 ; i >= 0 ; i--)
{
cout.width(DLEN);
cout.fill('0');
cout << b.a[i];
}
return out;
}
BigNum BigNum::operator+(const BigNum & T) const //两个大数之间的相加运算
{
BigNum t(*this);
int i,big; //位数
big = T.len > len ? T.len : len;
for(i = 0 ; i < big ; i++)
{
t.a[i] +=T.a[i];
if(t.a[i] > MAXN)
{
t.a[i + 1]++;
t.a[i] -=MAXN+1;
}
}
if(t.a[big] != 0)
t.len = big + 1;
else
t.len = big;
return t;
}
BigNum BigNum::operator-(const BigNum & T) const //两个大数之间的相减运算
{
int i,j,big;
bool flag;
BigNum t1,t2;
if(*this>T)
{
t1=*this;
t2=T;
flag=0;
}
else
{
t1=T;
t2=*this;
flag=1;
}
big=t1.len;
for(i = 0 ; i < big ; i++)
{
if(t1.a[i] < t2.a[i])
{
j = i + 1;
while(t1.a[j] == 0)
j++;
t1.a[j--]--;
while(j > i)
t1.a[j--] += MAXN;
t1.a[i] += MAXN + 1 - t2.a[i];
}
else
t1.a[i] -= t2.a[i];
}
t1.len = big;
while(t1.a[t1.len - 1] == 0 && t1.len > 1)
{
t1.len--;
big--;
}
if(flag)
t1.a[big-1]=0-t1.a[big-1];
return t1;
}
BigNum BigNum::operator*(const BigNum & T) const //两个大数之间的相乘运算
{
BigNum ret;
int i,j,up;
int temp,temp1;
for(i = 0 ; i < len ; i++)
{
up = 0;
for(j = 0 ; j < T.len ; j++)
{
temp = a[i] * T.a[j] + ret.a[i + j] + up;
if(temp > MAXN)
{
temp1 = temp - temp / (MAXN + 1) * (MAXN + 1);
up = temp / (MAXN + 1);
ret.a[i + j] = temp1;
}
else
{
up = 0;
ret.a[i + j] = temp;
}
}
if(up != 0)
ret.a[i + j] = up;
}
ret.len = i + j;
while(ret.a[ret.len - 1] == 0 && ret.len > 1)
ret.len--;
return ret;
}
BigNum BigNum::operator/(const int & b) const //大数对一个整数进行相除运算
{
BigNum ret;
int i,down = 0;
for(i = len - 1 ; i >= 0 ; i--)
{
ret.a[i] = (a[i] + down * (MAXN + 1)) / b;
down = a[i] + down * (MAXN + 1) - ret.a[i] * b;
}
ret.len = len;
while(ret.a[ret.len - 1] == 0 && ret.len > 1)
ret.len--;
return ret;
}
int BigNum::operator %(const int & b) const //大数对一个int类型的变量进行取模运算
{
int i,d=0;
for (i = len-1; i>=0; i--)
{
d = ((d * (MAXN+1))% b + a[i])% b;
}
return d;
}
BigNum BigNum::operator^(const int & n) const //大数的n次方运算
{
BigNum t,ret(1);
int i;
if(n<0)
exit(-1);
if(n==0)
return 1;
if(n==1)
return *this;
int m=n;
while(m>1)
{
t=*this;
for( i=1;i<<1<=m;i<<=1)
{
t=t*t;
}
m-=i;
ret=ret*t;
if(m==1)
ret=ret*(*this);
}
return ret;
}
bool BigNum::operator>(const BigNum & T) const //大数和另一个大数的大小比较
{
int ln;
if(len > T.len)
return true;
else if(len == T.len)
{
ln = len - 1;
while(a[ln] == T.a[ln] && ln >= 0)
ln--;
if(ln >= 0 && a[ln] > T.a[ln])
return true;
else
return false;
}
else
return false;
}
bool BigNum::operator >(const int & t) const //大数和一个int类型的变量的大小比较
{
BigNum b(t);
return *this>b;
}
void BigNum::print() //输出大数
{
int i;
printf("%d", a[len-1]);
for (int i = len-2; i >= 0; --i) {
printf("%04d", a[i]);
}
}
int main()
{
int t, n;
cin >> t;
while(t--)
{
scanf("%d", &n);
BigNum cnt = 1, ans = 0;
for(int i = 1; i <= n; i++)
{
cnt = cnt * i;
};
for(int i = 1; i <= n; i++)
{
ans = ans + cnt/i;;
BigNum tmp = (cnt/i);
}
ans.print();
printf(".0\n");
}
return 0;
}
8 Cantonese
————————————————————————————————————
9 Magic
————————————————————————————————————
10 Trades
————————————————————————————————————
11 Wand
————————————————————————————————————
有n个人,每个人有一个物品,问你打乱这些物品后至少有K个人还拿到自己的物品的可能数
水题, 但是我tm还是wa了一发。。 爆了long long;
枚举k, 然后剩下的错排就好了, 这题应该n再大一点2e7左右, 因为k就100, 很明显暗示我们要将“至少“转化...可是这题没卡
代码转自tabris
#include<stdio.h>
#include<string.h>
using namespace std;
#define LL long long int
const int N = 1e5 + 7;
const int MOD = 1e9+7;
/**********************************/
LL qmod(LL a,LL b) {
LL res = 1ll;
while(b) {
if(b&1) res=res*a%MOD;
b>>=1,a=a*a%MOD;
}
return res;
}
LL dp[N];
LL fac[N],inv[N];
void init() {
fac[0]=1;
for(LL i=1; i<N; i++) fac[i]=(fac[i-1]*i)%MOD;
inv[N-1] = qmod(fac[N-1],MOD-2);
for(LL i=N-2; i>=0; i--) inv[i]=(inv[i+1]*(i+1))%MOD;
}
LL C(int n,int m) {
return fac[n]*inv[m]%MOD*inv[n-m]%MOD;
}
int main() {
init();
dp[0]=1;
dp[1]=0;
for(LL i=1; i<=10000; i++) {
dp[i]=(i-1)*(dp[i-1]+dp[i-2]);
dp[i]%=MOD;
}
int t;
int n,kk;
scanf("%d",&t);
while(t--) {
scanf("%d%d",&n,&kk);
LL output=0;
for(int k=kk; k<=n; k++) {
output+=C(n,k)*dp[n-k]%MOD;
output%=MOD;
}
printf("%I64d\n",output%MOD);
}
return 0;
}
12 Tic-Tac-Toe
————————————————————————————————————
两个人下井字棋,现在轮到Kim下,问你Kim在下两个子的内能不能赢