纪念一下和库里布莱恩特的这场菜鸡互啄。
3星Gym,一共做出来7个题。感觉最大的收获就是意识到了二分的重要性,还有就是学习到了一种新的排序方法——计数排序(好像又叫桶排序)。下面根据题的难度从简到难记录一下。
H题:
按照题意打印即可。
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define ll long long
#define ull unsigned long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1或false或true
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
#define inf 0x3f3f3f3f//1e9+6e7
#define eps 1e-8
#define mod 1e9+7
#define N 100010
const double pi=acos(-1.0);
using namespace std;
int main()
{
int n;
cin>>n;
rep(i,1,n)
{
if(i==1)
{
cout<<"*";
rep(j,1,n-2)
cout<<" ";
cout<<"* ";
rep(j,1,n)
cout<<"*";
cout<<endl;
continue;
}
if(i==n)
{
rep(j,1,n)
cout<<"*";
cout<<" *";
rep(j,1,n-2)
cout<<" ";
cout<<"*";
continue;
}
cout<<"*";
rep(j,1,n-2)
cout<<" ";
cout<<"*";
cout<<" *";
rep(j,1,n-2)
cout<<" ";
cout<<"*"<<endl;
}
return 0;
}
D题:
说是有两种机器A和B,对于A:输入x,返回2*x+1;对于B,输入x,返回2*x+2。开始有0个,要得到n个,问应该怎样使用机器。
只需要判断n的奇偶性就性了,如果n为奇数,用A,否则用B,一直判断,直到n为0,然后倒序输出即可。
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define repp(i,n,a) for(int i=n;i>=a;i--)
#define ll long long
#define ull unsigned long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1或false或true
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
#define inf 0x3f3f3f3f//1e9+6e7
#define eps 1e-8
#define mod 1e9+7
#define N 100010
const double pi=acos(-1.0);
using namespace std;
char ans[1000010];
int main()
{
ll n;
cin>>n;
mem(ans,0);
int k=0;
while(n)
{
if(n%2==0)
{
ans[k]='B';
k++;
n=(n-2)/2;
}
else
{
ans[k]='A';
k++;
n=(n-1)/2;
}
}
repp(i,k-1,0)
cout<<ans[i];
return 0;
}
B题:
有一棵树,给你n个数,a[i]表示某一层的每个节点都可以有a[i]个子节点,问这颗树最多有多少个节点。猜都能猜出来,让深度越浅的层数有越多的节点。
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define ll long long
#define ull unsigned long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1或false或true
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
#define inf 0x3f3f3f3f//1e9+6e7
#define eps 1e-8
#define mod 1e9+7
#define N 100010
const double pi=acos(-1.0);
using namespace std;
int a[40];
bool cmp(int a1,int a2)
{
return a1>a2;
}
int main()
{
int n;
cin>>n;
rep(i,0,n-1)
cin>>a[i];
sort(a,a+n,cmp);
ll ans=1;
ll cnt=1;
rep(i,0,n-1)
{
ans+=(cnt*a[i]);
cnt=cnt*a[i];
}
cout<<ans;
return 0;
}
C题:
在三维平面里,给你n个点的坐标,第一个点表示地球,其余n-1个点表示其他行星,问从其他n-1个行星到地球连线,共能产生多少条不同的直线。只需要算出向量坐标然后比较即可。比如两个向量,判断其是否共线,假设这两个个向量分别为(x1,y1,z2),(x2,y2,z2),如果满足x1/x2==y1/y2&&x1/x2==z1/z2,则共线,否则不共线。但是,需要注意的是,坐标可能有0,0不能做除数,所以要转化成乘法来做,及判断x1*y2==y2*x2&&x1*z2==z1*x2&&y2*z1==z2*y1是否成立。
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define ll long long
#define ull unsigned long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1或false或true
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
#define inf 0x3f3f3f3f//1e9+6e7
#define eps 1e-8
#define mod 1e9+7
#define N 100010
const double pi=acos(-1.0);
using namespace std;
struct node{
int x1,y1,z1;
int x2,y2,z2;
}a[5010];
int vis[5010];
int main()
{
int n;
cin>>n;
int x,y,z;
cin>>x>>y>>z;
rep(i,0,n-2)
{
cin>>a[i].x1>>a[i].y1>>a[i].z1;
a[i].x2=x-a[i].x1;
a[i].y2=y-a[i].y1;
a[i].z2=z-a[i].z1;
}
mem(vis,0);
int cnt=0;
rep(i,0,n-2)
{
if(vis[i])
continue;
vis[i]=1;
cnt++;
rep(j,0,n-2)
if(a[i].x2*a[j].y2==a[i].y2*a[j].x2&&a[i].x2*a[j].z2==a[i].z2*a[j].x2&&a[i].z2*a[j].y2==a[i].y2*a[j].z2)
vis[j]=1;
}
cout<<cnt;
return 0;
}
F题:
猜的题意,因为我看好几个人都一发过了,然后我感觉题应该很简单,然后就猜了一下,码了一下,交了一发,过了......
判断n个“三角形”是不是都能构成三角形,如果存在不能构成三角形的三角形,输出NO,否则输出YES。
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define ll long long
#define ull unsigned long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1或false或true
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
#define inf 0x3f3f3f3f//1e9+6e7
#define eps 1e-8
#define mod 1e9+7
#define N 100010
const double pi=acos(-1.0);
using namespace std;
struct node{
int x,y,z;
}a[100010];
int main()
{
int n;
cin>>n;
int xx,yy,zz;
int f=0;
rep(i,0,n-1)
{
scanf("%d%d%d",&xx,&yy,&zz);
a[i].x=max(max(xx,yy),zz);
a[i].z=min(min(xx,yy),zz);
a[i].y=xx+yy+zz-a[i].x-a[i].z;
}
rep(i,0,n-1)
{
if(a[i].z+a[i].y>a[i].x)
continue;
else
{f++;break;}
}
if(f)
cout<<"NO";
else
cout<<"YES";
return 0;
}
E题:
给你两个字符串A和B,再给你一个整数n,让你输出B在A中出现次数大于等于n次的最长前缀串,如果不存在输出impossible。
首先需要知道,如果B的长度为i的前缀串在A中出现的次数不足n次,那么B中长度为i+1的前缀串在A中出现的次数一定也不足n次。并且我们可以在O(n+m)时间范围内判断一个长度为m的模式串在一个长度为n的主串中出现的次数(直接套模板)。如果我们对模式串的长度从1到strlen(B)枚举的话,时间复杂度为1e5*1e5,会超时,所以我们可以用二分,二分模式串的长度。
二分真的很重要啊,当算法超时的时候一定要想想二分啊!
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define ll long long
#define ull unsigned long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1或false或true
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
#define inf 0x3f3f3f3f//1e9+6e7
#define eps 1e-8
#define mod 1e9+7
#define N 100010
const double pi=acos(-1.0);
using namespace std;
char S[100010];
char TT[100010];
char T[100010];
int slen,tlen,ttlen;
char ans[100010];
int nxt[100010];
void getNext()
{
int i,j;
i=0;j=-1;nxt[0]=-1;
while(i<tlen)
{
if(j==-1||T[i]==T[j])
nxt[++i]=++j;
else
j=nxt[j];
}
}
int KMP_Count()
{
int ret=0;
int i,j=0;
if(slen==1&&tlen==1)
{
if(S[0]==T[0])
return 1;
else
return 0;
}
getNext();
for(i=0;i<slen;i++)
{
while(j>0&&S[i]!=T[j])
j=nxt[j];
if(S[i]==T[j])
j++;
if(j==tlen)
{
ret++;
//j=i+1; //如果求主串中包含几个模式串 j=i+1
j=nxt[j];//如果求模式串在主串中出现的次数 j=nxt[j]
}
}
return ret;
}
int main()
{
gets(S);
gets(TT);
int k;
cin>>k;
ttlen=strlen(TT);
slen=strlen(S);
int f=0;
ans[0]='!';
int l=1,r=ttlen;
while(l<=r)
{
int mid=(l+r)/2;
rep(j,0,mid-1)
T[j]=TT[j];
T[mid]='\0';
tlen=mid;
if(KMP_Count()<k) //KMP_Count()返回模式串T在主串S中出现的次数
r=mid-1;
else
{strcpy(ans,T);l=mid+1;}
}
if(ans[0]=='!')
cout<<"IMPOSSIBLE";
else
cout<<ans;
return 0;
}
J题:
某人想写出n个数,但是当他写完m(m<n)个数时,他不想写了,要直接构造出来n-m个数,构造公式:a[i]=(a[i-m]+a[i-m+1])%3e7。然后进行k次询问,每次询问给出一个数b[i],问将上面n个数排好序后,第b[i]个数是多少。
这个题有两种方法可以做,一种是计数排序(桶排序),另一种是思维......实际上和计数排序差不多。
1、计数排序
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define repp(i,n,a) for(int i=n;i>=a;i--)
#define ll long long
#define ull unsigned long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1或false或true
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
#define inf 0x3f3f3f3f//1e9+6e7
#define eps 1e-8
#define mod 1e9+7
#define N 100010
const double pi=acos(-1.0);
using namespace std;
int a[30000010];
int b[30000010];
int c[10000010];
int main()
{
int n,m,q;
cin>>n>>m>>q;
int maxx=-10;
mem(b,0);
rep(i,1,m)
{
scanf("%d",&a[i]);
maxx=max(maxx,a[i]);
b[a[i]]++;
}
rep(i,m+1,n)
{
a[i]=(a[i-m]+a[i-m+1])%30000000;
maxx=max(maxx,a[i]);
b[a[i]]++; //b[i]表示i出现的次数
}
int k=1;
//计数排序
rep(i,0,maxx)
{
rep(j,1,b[i])
{c[k]=i;k++;} //数组c即为将a数组排好序的结果
}
int x;
while(q--)
{
scanf("%d",&x);
cout<<c[x]<<endl;
}
return 0;
}
2、思维,实际上都差不多。
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define repp(i,n,a) for(int i=n;i>=a;i--)
#define ll long long
#define ull unsigned long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1或false或true
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
#define inf 0x3f3f3f3f//1e9+6e7
#define eps 1e-8
#define mod 1e9+7
#define N 100010
const double pi=acos(-1.0);
using namespace std;
int a[30000010];
int b[30000010];
int main()
{
int n,m,q;
cin>>n>>m>>q;
mem(b,0);
rep(i,1,m)
{scanf("%d",&a[i]);b[a[i]]++;}
rep(i,m+1,n)
{
a[i]=(a[i-m]+a[i-m+1])%30000000;
b[a[i]]++;
}
rep(i,1,30000000)
b[i]=b[i]+b[i-1];
int x;
while(q--)
{
scanf("%d",&x);
int l=0,r=30000000;
while(l<=r)
{
int mid=(l+r)/2;
if(b[mid]>=x&&b[mid-1]<x)
{cout<<mid<<endl;break;}
if(b[mid]<x)
l=mid+1;
else
r=mid-1;
}
}
return 0;
}
其他的暂时不会了,慢慢补吧......