luogu.org 试炼场关卡2—21 简单数学

版权声明:https://blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/85852472

p1374 倒水 进制 || 枚举、暴力

题目

https://www.luogu.org/problemnew/show/P1582

题解

一句话题意:将n加x,使得他们的和在二进制下有<=k个1,且x最小。
理解了题意,其实就很简单了:
1.码出求n(包括n+x)在二进制下有几个1的函数;(如果不会,网上学习。)
2.使用一下lowbit(就是树状数组的那个lowbit);
然后,你就会发现这道题就A了!!!!!
不懂就继续往下看!

引用一下 https://www.luogu.org/blog/user36297/solution-p1582
这题第一眼看到就知道和二进制有关。

合并前 二进制 合并后
1个瓶子 1 1个瓶子
2个瓶子 10 1个瓶子
3个瓶子 11 2个瓶子
4个瓶子 100 1个瓶子
5个瓶子 101 2个瓶子
6个瓶子 110 2个瓶子
7个瓶子 111 3个瓶子
8个瓶子 1000 1个瓶子

根据上列式子,我们知道n个有水的瓶子,最后合并成的瓶子个数,就是这个数转成二进制1的个数。
我们知道,二进制有一个很好的取各位上1的个数的方法。
首先我们来认识一个式子:

i&-i(C++),i and -i(pascal)

这个式子返回的值就是从后往前数,到第一个1出现为止的数(二进制下)。
来列个表:

i i(2) i&-i i&-i(2)
1 1 1 1
2 10 2 10
3 11 1 1
4 100 4 100
5 101 1 1
6 110 2 10
7 111 1 1
8 1000 8 1000

然后,如果要取x中1的个数(二进制下),那么就写这样一段代码:

int work(int x)
{
	int num=0;
	for (;x;x-=x&-x)
		++num;
	return num;
}

num就是1的个数。
然后,我们解决添加的问题,一个个添加太慢了,我们应该一次添加一堆,这一堆添上去,刚好能让总共的水杯个数减少(或不变)。
我们有个贪心的想法,从少的开始添,否则就浪费了,明明可以要黄金,你却偏偏喜欢白银(我也无能为力)。
那么就用到上面的这个式子了,在最后一位1再添上个1,那么就会进位,水杯的个数只会减少(或不变),而不会增多。
最后个数小于等于k时就可以停了。

代码

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
	int f=1,num=0;
	char ch=getchar();
	while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar(); }
	while (isdigit(ch)) num=(num<<1)+(num<<3)+(ch^48), ch=getchar();
	return num*f;
}
int lowbit(int x)
{
	return x & -x;
}
int count_one_bits(unsigned int n)
{
	int count = 0;
	for (int i=1;i;i<<=1)//判断每一位的值是否为1
	{
		if ((n & 1)==1)
			++count;
		//右移准备判断下一位的值
		n>>=1;
	}
	return count;
}
int main()
{
	int n=read(),k=read(),ans=0;
	while (count_one_bits(n)>k)
		ans+=lowbit(n),n+=lowbit(n);
	printf("%d\n",ans);
	return 0;
}

p2158 [sdoi2008]仪仗队 素数判断,质数,筛法 || 最大公约数,gcd

题目

https://www.luogu.org/problemnew/show/P2158

题解

《算法竞赛进阶指南》。。。。。。。。T_T

代码

#include<bits/stdc++.h>
#define up(i,a,b) for (register int i=a;i<=b;++i)
#define down(i,a,b) for (register int i=a;i>=b;--i)
using namespace std;
const int maxn=4e4+10;
inline int read()
{
	int f=1,num=0;
	char ch=getchar();
	while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar(); }
	while (isdigit(ch)) num=(num<<1)+(num<<3)+(ch^48), ch=getchar();
	return num*f;
}
int ans;
int v[maxn],prime[maxn],phi[maxn];
void eular(int n)
{
	memset(v,0,sizeof(v));//最小质因子 
	int m=0;//质数数量
	up(i,2,n)
	{
		if (!v[i])//i是质数 
		{
			v[i]=i,prime[++m]=i;
			phi[i]=i-1;
		}
		up(j,1,m)//给当前的数i乘上一个质因子 
		{
			if (prime[j]>v[i] || prime[j]>n/i) break;
			//i有比prime[j]更小的质因子,或者超出n的范围 
			v[i*prime[j]]=prime[j];//prime[j]是合数i*prime[j]的最小质因子 
			phi[i*prime[j]]=phi[i]*(i%prime[j] ? prime[j]-1 : prime[j]);
		}
	}
}
int main()
{
	int n=read();
	if (n==1)
	{
		puts("0");
		exit(0);
	}
	eular(n);
	up(i,2,n-1)
		ans+=phi[i];
	printf("%d\n",ans*2+3);
	return 0;
}

P1372 又是毕业季I 最大公约数,gcd

题目

https://www.luogu.org/problemnew/show/P1372

代码

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
	int f=1,num=0;
	char ch=getchar();
	while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar(); }
	while (isdigit(ch)) num=(num<<1)+(num<<3)+(ch^48), ch=getchar();
	return num*f;
}
int main()
{
	int n=read(),k=read();
	printf("%d\n",n/k);
	return 0;
}

总之,我想吐血。。。。。。。

P1865 A % B Problem 前缀和||素数判断,质数,筛法

题目

https://www.luogu.org/problemnew/show/P1865

代码

#include<bits/stdc++.h>
#define up(i,a,b) for (register int i=a;i<=b;++i)
#define down(i,a,b) for (register int i=a;i>=b;--i)
using namespace std;
const int maxn=1e6+10;
inline int read()
{
	int f=1,num=0;
	char ch=getchar();
	while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar(); }
	while (isdigit(ch)) num=(num<<1)+(num<<3)+(ch^48), ch=getchar();
	return num*f;
}
int v[maxn],f[maxn];
void primes(int n)
{
	v[1]=1;
	f[1]=0;
	up(i,2,n)
	{
		if (!v[i])
		{
			f[i]=f[i-1]+1;
			up(j,i,n/i)
				v[i*j]=1;
		}
		else f[i]=f[i-1];
	}
}
int main()
{
	int n=read(),m=read();
	primes(maxn);
	up(i,1,n)
	{
		int l=read(),r=read();
		if (l<1 || r>m)
			puts("Crossing the line");
		else
		{
			int ans=f[r]-f[l-1];
			printf("%d\n",ans);
		}
	}
	return 0;
}

任务完成!正式通关!还剩一题,不写,让他见鬼去吧

猜你喜欢

转载自blog.csdn.net/huashuimu2003/article/details/85852472