国庆七连测——4

今天终于有时间写博客了
蒟蒻前几天忙于订正题目。。。
今天题目比较简单所以才有时间来写博客。(昨天最后一题还没有搞懂。。km当初没学只学了匈牙利)

第一题

给你n根相同的木棍平均分给m个人
问木棍一共要分次。
这道题很简单,直接用gcd判断当分到第几个人时要不要切割。
n表示木棍根数
ns表示切到第几根木棍
m表示总人数
ms表示已经分的人数
所以如果ns/n==ms/m
那么就是给这个人分的时候不需要切割
所以就可以o(m)出解

代码

#include<cstdio>
#include<cstring>
int ans=0;
int n,m;
int gcd(int x,int y)
{
	if(y==0)
	{
		return x;
	}
	else
	{
		return gcd(y,x%y);
	}
}
int main()
{
	freopen("kusac.in","r",stdin);
	freopen("kusac.out","w",stdout);
	scanf("%d %d",&n,&m);
	int ns=1,ms=1;
	int ans=0;
	while(ms<=m)
	{
		while(((double)ms/m)>((double)ns/n))
		{
			ns++;
		}
		int gcdn=gcd(n,ns);
		int gcdm=gcd(m,ms);
		int nowns=ns/gcdn;
		int nown=n/gcdn;
		int nowms=ms/gcdm;
		int nowm=m/gcdm;
		if(nowns==nowms&&nown==nowm)
		{
			ms++;
		}
		else
		{
			ans++;
			ms++;
		}
	}
	printf("%d",ans);
	return 0;
}

第二题

给你n个物品,有重量(w)和价值(v)
k个背包每个背包只能有一本书,且有限制重量(c)
我是这样做的
将n个物品按重量排序
将k个背包按限制重量排序
然后两个指针指着背包和物品的最前端(最小限制重量和最小重量)
然后我们从第一个背包开始
如果物品可以放入那么就将物品价值放进优先队列
直到物品不能再放入
然后将优先队列中最大的价值放到背包中
最后所有背包总价值就是答案

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
int n,k;
struct thing
{
	int w,v;
}t[300010];
int bag[300010];
bool cmp(thing a,thing b)
{
	return a.w<b.w;
}
priority_queue <int,vector<int>,less<int> >q;
long long ans=0;
int main()
{
	freopen("lopov.in","r",stdin);
	freopen("lopov.out","w",stdout);
	memset(t,0,sizeof(t));
	memset(bag,0,sizeof(bag));
	scanf("%d %d",&n,&k);
	for(int i=1;i<=n;i++)
	{
		scanf("%d %d",&t[i].w,&t[i].v);
	}
	for(int i=1;i<=k;i++)
	{
		scanf("%d",&bag[i]);
	}
	sort(t+1,t+1+n,cmp);
	sort(bag+1,bag+1+k);
	int flagt=1;
	int flagbag=1;
	while(flagbag<=k)
	{
		while(t[flagt].w<=bag[flagbag]&&flagt<=n)
		{
			q.push(t[flagt].v);
			flagt++;
		}
		if(!q.empty())
		{
			ans+=q.top();
			q.pop();
		}
		flagbag++;
	}
	printf("%lld\n",ans);
	return 0;
}

第三题

给你一个n*n的矩阵
让你在其中找出两个子矩阵
满足元素和一样
且仅有一个角相邻
类似于这样
1 1 0 0
1 1 0 0
0 0 1 1
0 0 1 1(忽略0)
1 2 0
2 3 0
0 0 8(忽略0)
于是我就想将每个矩阵和算出
以每个矩阵和为下标,记录下矩阵的左上角和右下角坐标
然后按不同的矩阵面积来处理
分别用四个二维数组来存有几个矩阵的四个角到达这里
(分别右下角、右上角、左下角、左上角)
然后n^2扫一遍就可以求出解了

代码

#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
int n;
int read[61][61];
int add[61][61];
struct piece
{
	int x1,y1,x2,y2;
};
vector <piece> g[5000010];
vector <int> have;
int checkzs[61][61];
int checkrs[61][61];
int checkzx[61][61];
int checkrx[61][61];
bool used[5000010];
long long ans=0;
int main()
{
	freopen("ratar.in","r",stdin);
	freopen("ratar.out","w",stdout);
	memset(read,0,sizeof(read));
	memset(add,0,sizeof(add));
	memset(used,0,sizeof(used));
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			scanf("%d",&read[i][j]);
			add[i][j]=read[i][j]+add[i-1][j]+add[i][j-1]-add[i-1][j-1];
		}
	}
	for(int x1=1;x1<=n;x1++)
	{
		for(int y1=1;y1<=n;y1++)
		{
			for(int x2=x1;x2<=n;x2++)
			{
				for(int y2=y1;y2<=n;y2++)
				{
					int squre=add[x2][y2]+add[x1-1][y1-1]-add[x2][y1-1]-add[x1-1][y2]+2500000;
					g[squre].push_back((piece){x1,y1,x2,y2});
					if(used[squre]==0)
					{
						used[squre]=1;
						have.push_back(squre);
					}
				}
			}
		}
	}
	for(int k=0;k<have.size();k++)
	{
		memset(checkzs,0,sizeof(checkzs));
		memset(checkrs,0,sizeof(checkrs));
		memset(checkzx,0,sizeof(checkzx));
		memset(checkrx,0,sizeof(checkrx));
		int now=have[k];
		for(int i=0;i<g[now].size();i++)
		{
			checkzs[g[now][i].x1][g[now][i].y1]++;
			checkrs[g[now][i].x1][g[now][i].y2]++;
			checkzx[g[now][i].x2][g[now][i].y1]++;
			checkrx[g[now][i].x2][g[now][i].y2]++;
		}
		for(int x=1;x<=n;x++)
		{
			for(int y=1;y<=n;y++)
			{
				if(checkrx[x][y]&&checkzs[x+1][y+1])
				{
					ans+=checkrx[x][y]*checkzs[x+1][y+1];
				}
				if(checkzx[x][y]&&checkrs[x+1][y-1])
				{
					ans+=checkzx[x][y]*checkrs[x+1][y-1];
				}
			}
		}
	}
	printf("%lld\n",ans);
	return 0;
}

然而由于玄学
我的这个程序在评测是满分
自己数据测要一点几秒
别人数据测要两秒
oj上测也要一点二秒。。。
stl的劣根性(vector)
可以用链表代替
flag:我就是饿死,从这里跳下去,死外边,也不用stl了!
真香!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值