A.蛋挞
题目链接
分析:签到题,其他人分的尽量多且一样那就是n/m,剩下的余数就是牛牛吃的,比较n/m,n%m大小即可。注意数值范围。
#include<bits/stdc++.h>
using namespace std;
long long n,m;
int main()
{
cin>>n>>m;
long long a=n/m;
long long b=n%m;
if(a>b)
{
puts("niuniu eats less than others");
}
else if(a<b)
{
puts("niuniu eats more than others");
}
else puts("same");
return 0;
}
B.玩具
题目链接
分析:购买两个即可免单较低的那个,那最贵的是必须花钱买的,但是免的可以是任何一个,分析可知免第二贵的是最划算的,同理可证。所以进行排序,如果个数是偶数,那么偶数位的均要花钱,而奇数位免单;如果个数是奇数,那么奇数位花钱,偶数位免单。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
long long n,res;
long long a[N];
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
if(n%2)
{
for(int i=1;i<=n;i+=2) res+=a[i];
}
else
{
for(int i=2;i<=n;i+=2) res+=a[i];
}
cout<<res<<endl;
return 0;
}
C.开题顺序
题目链接
分析:由于这组数据非常小只有9个,而且还是连续的,所以全排列模拟一下即可求出答案。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 20;
int n,tt,k,res,sum;
bool st[N];
struct Node
{
int a,b,c,x,y;
}p[N];
void dfs(int t,int sum)
{
res=max(res,sum);
for(int i=1;i<=n;i++)
{
if(t+p[i].x<=tt&&!st[i])
{
st[i]=true;
dfs(t+p[i].x,sum+max(p[i].c,p[i].a-(t+p[i].x)*p[i].b-p[i].y*k));
st[i]=false;
}
}
return;
}
signed main()
{
cin>>n>>tt>>k;
for(int i=1;i<=n;i++) cin>>p[i].a>>p[i].b>>p[i].c>>p[i].x>>p[i].y;
dfs(0,0);
cout<<res<<endl;
return 0;
}
D.旅游
题目链接
分析:这题几乎为最小生成树的板子,但需要知道一个结论,例如有两条路的损坏值为2和3,先修3再修2会比先修2再修3耗费小,3*1+2*2<2*1+3*2。所以这里采用kruskal板子,然后那个数组记录最小生成数的路径花费,这一定是有序的,再根据上面那个结论先修最大的,直到钱不够就让国家修复即可。如果全修复了输出0就行。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 4e4+10,M = 1e5+10;
int n,m,c;
int p[N],t[N];
struct Edge
{
int a,b,w;
}g[M];
bool cmp(Edge a,Edge b)
{
return a.w<b.w;
}
int find(int x)
{
if(x!=p[x]) p[x]=find(p[x]);
return p[x];
}
void kruskal()
{
sort(g+1,g+m+1,cmp);
for(int i=1;i<=n;i++) p[i]=i;
int cnt=0;
for(int i=1;i<=m;i++)
{
int a=g[i].a,b=g[i].b,w=g[i].w;
int pa=find(a),pb=find(b);
// printf("a---%d pa---%d,b---%d pb---%d,w---%d\n",a,pa,b,pb,w);
if(pa!=pb)
{
p[pa]=p[pb];
t[++cnt]=w;
}
}
// for(int i=1;i<=cnt;i++) printf("%d ",t[i]);
// puts("");
for(int i=cnt,k=1;i>=1;i--,k++)
{
c-=k*t[i];
if(c<0)
{
cout<<t[i]<<endl;
return;
}
}
puts("0");
}
signed main()
{
cin>>n>>m>>c;
for(int i=1;i<=m;i++)
{
int a,b,w;
cin>>g[i].a>>g[i].b>>g[i].w;
}
kruskal();
}
E.等腰三角形(easy)
题目链接
分析:由于数据范围很小,暴力枚举即可。复杂度为o(
n
3
n^3
n3)。别忘了排除三点共线的情况。
#include<bits/stdc++.h>
using namespace std;
const int N = 500;
int n,res;
struct Node
{
int x,y;
}a[N];
int d(Node a,Node b)
{
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
bool check1(Node a,Node b,Node c)
{
if((c.x-b.x)*(b.y-a.y)==(c.y-b.y)*(b.x-a.x)) return false;
return true;
}
bool check2(Node a,Node b,Node c)
{
if(((d(a,b)==d(a,c)||d(a,b)==d(b,c)||d(a,c)==d(b,c))&&check1(a,b,c))) return true;
return false;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i].x>>a[i].y;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
for(int k=j+1;k<=n;k++)
{
if(check2(a[i],a[j],a[k])) res++;
}
}
}
cout<<res<<endl;
return 0;
}
F.等腰三角形(hard)
题目链接
分析:枚举每个点当顶点,然后以边长进行枚举,统计所有边长相等的边,进行边记录边相加,最终得出的结果和从这些相等里面选出两条的选法数是相等的,最后和上一题一样要排除共线,那个sum来存储,根据两点可以求出对称点的位置,如果有就sum++,由于对称会被枚举两次,最后结果需要除以2。注意偏移量的大小。
#include<bits/stdc++.h>
using namespace std;
const int N = 3010,M = 2e6+10,Base = 1500;
int n;
int cnt[M];
int x[N],y[N];
bool st[N][N];
int dis(int a,int b)
{
return (x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]);
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x[i]>>y[i];
st[x[i]+Base][y[i]+Base]=true;
}
long long res=0,sum=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j) continue;
res+=cnt[dis(i,j)];
cnt[dis(i,j)]++;
if(st[2*x[i]-x[j]+Base][2*y[i]-y[j]+Base]) sum++;
}
for(int j=1;j<=n;j++)
{
if(i==j) continue;
cnt[dis(i,j)]=0;;
}
}
cout<<res-sum/2<<endl;
return 0;
}
补题仅到此为止,最后一题脑瓜子转不动了。如果有错误欢迎纠正。