题目描述:
牛牛喜欢做题。但他不喜欢做难题,喜欢做水题。
对于一个题号为i的题而言,题目的难度为i的所有因子之和除以i。牛牛认为难度小于2的题目都是水题。
例如:
编号为25的题目,其难度为(1+5+25)/25=1.24<2,因此这道题是水题。
编号为28的题目,其难度为(1+2+4+7+14+28)/28=2,因此这道题不是水题。
编号为30的题目,其难度为(1+2+3+5+6+10+15+30)/30=2.4>2,因此这道题也不是水题。
牛牛拿到了一个共有n道题目的题单,上面的题号为1、2、3、…、n。牛牛把上面所有的水题刷了个遍。每做一道编号为i的水题,牛牛可以获得i的快乐指数。
牛牛想知道,自己一共能获得多少快乐指数?
明显是一道水题,两个循环,第一个循环是从1到n遍历一遍,嵌套着第二个循环找到所有的因子,并求和,然后与2 * n比较,计算快乐指数。
#include
using namespace std;
int main()
{
int n;
int ans = 0, sum = 0;
cin>>n;
for(int i = 1; i <= n; i++)
{
sum = 0;
for(int j = 1; j <= i; j++)
{
if(i % j == 0) sum++;
}
if(sum < 2 * i) ans+=i;
}
cout<
题目描述:
牛牛现在在花园养了n棵树,按顺序从第1棵到第n棵排列着。牛牛每天会按照心情给其中某一个区间的树浇水。例如如果某一天浇水的区间为[2,4],就是牛牛在这一天会给第2棵,第3棵和第4棵树浇水。树被浇水后就会成长,为了简化问题,我们假设在初始时所有树的高度为0cm。每过去一天树会自然成长1cm,每次树被浇水后当天会额外成长1cm。m天中牛牛每天都都会选一个区间[l,r]对这个区间内的树进行浇水,牛牛想知道m天后有多少棵树的高度为奇数,你能告诉牛牛吗?
这个题时间是三秒,可以暴力过,但是还可以用到一个算法,叫差分前缀和……
先看一下暴力的方法:
#include
using namespace std;
int main()
{
int tr[10005];
int n, m, a, b;
int ans = 0;
cin>>n>>m;
for(int i = 0; i < m; i++)
{
cin>>a>>b;
for(int j = a; j <= b; j++)
tr[j]++;
}
for(int i = 1; i <= n; i++)
{
if((tr[i] + m) % 2 == 1)
ans++;
}
cout<
用了2007毫秒的时间,属实很慢,一般比赛都会直接TL
我们来看一下差分前缀和怎么实现
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 返回m天后高度为奇数的树的数量
* @param n int整型
* @param m int整型
* @param l int整型vector
* @param r int整型vector
* @return int整型
*/
int oddnumber(int n, int m, vector& l, vector& r) {
// write code here
int sum[200020] = {0};
int ans = 0;
for(int i = 0; i < m; i++)
{
sum[l[i]]++;
sum[r[i] + 1]--;
}
for(int i = 1; i <= n; i++)
{
sum[i] += sum[i - 1];
}
for(int i = 1; i <= n; i++)
{
if((sum[i] + m) % 2 == 1)
ans++;
}
return ans;
}
};
查分前缀和见我的博客此处不详讲
自助餐厅里有5个盘子,里面装的都是面包。
第1个盘子里有无限个面包;
第2个盘子里只有1个面包;
第3个盘子里只有4个面包;
第4个盘子里也有无限个面包,但必须两个两个地拿;
第5个盘子里也有无限个面包,但必须5个5个地拿;
给定正整数n,求有多少种正好拿出n个面包的方案。
方案a和方案b不同,当且仅当方案a存在从某个盘子里拿出面包的数量与方案b中对应盘子拿出的数量不同。
这个题大眼一看需要五个for循环,但是这样必然超时!
那我们从问题入手,转换成数学语言是x + y + z + 2 * a + 5 * b = n(y<= 1 , z <= 4)
在利用加法交换律和结合律,x + (y + a * 2) + (z + b * 5) = n,这样的话就可以看做是三个整数相加的和为n,求有几种方法,这就是高二数学讲排列组合时候的插空法的变性,分三种情况,第一种就是这三个数有两个都是0,就是不存在的时候,这个是 C(3,1) = 3 ;第二种情况是有两个数来分这个n,一个数不存在,就是C(3,2) * (n - 1),这个n - 1就是插空法的挡板,第三种情况是三个数都用来构成这个n,所以就是直接的插空法C(n-1,2),三种情况想加,得到最终表达式(n + 1)* (n +2) / 2.
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param n int整型
* @return long长整型
*/
long long wwork(int n) {
// write code here
return 1ll * (n + 1) * (n + 2) / 2;
}
};
千万别忘了乘以1ll,不然会wa.
牛牛在做数学实验。
老师给了牛牛一个数字n,牛牛需要不断地将所有数位上的值做乘法运算,直至最后数字不发生变化为止。
请你帮牛牛计算一下,最后生成的数字为多少?
思路:当n小于10的时候,最后的数字就不会改变了,所以n<10就是循环截止的条件,然后我们只需要在循环内嵌套一个循环,用来将每一位的数相乘即可
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param n long长整型 老师给牛牛的数字
* @return int整型
*/
int mathexp(long long n) {
int ans;
while(n >= 10)
{
ans = 1;
while(n)
{
ans *= n % 10;
n /= 10;
}
n = ans;;
}
return n;//一定要记得返回n不是返回ans,因为如果输入的是小于0的数,返回n才是对的
}
};
操场上有n个人排成一队,这n个人身高互不相同,可将他们的身高视为一个1到n的排列。
这时需要把队伍变成升序,也就是从矮到高排序。
每次可以选择一个人,让这个人和在他身后的人比高矮,如果比对方高,则交换位置并继续下一次比较,直到比对方矮或者已经在队尾。
现在给出数n和一个1到n的排列,求最少的选择次数,使队伍变为升序。
这是个思维题,从队列尾部开始往前判断,因为是要找变为升序的最少次数,就是判断一下,tr[i] 与 minx比较,minx 初始是最大值(本题是n + 1),如果前者大,则将前者的值赋给minx,不计数,再继续循环;如果后者大,说明tr[i]得交换,所以加一,minx不变。
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param n int整型
* @param a int整型vector
* @return int整型
*/
int wwork(int n, vector& a) {
int ans = 0;
int minx = n + 1;
for(int i = n - 1; i >= 0; i--)
{
if(a[i] > minx) ans++;
else minx = a[i];
}
return ans;
}
};
牛牛最近学会了异或操作,于是他发现了一个函数f(x)=x⊕(x−1)f(x)=x\oplus (x-1)f(x)=x⊕(x−1),现在牛牛给你一个数n\mathit nn,他想知道∑i=1nf(i)\sum_{i=1}^n f(i)∑i=1nf(i)的值是多少,请你告诉他。
直接莽暴力
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param n int整型
* @return long长整型
*/
long long Sum(int n) {
long long sum = 0;
for(int i = 1; i <= n; i++)
{
sum += i ^(i - 1);
}
return sum;
}
};
看了别人的代码,有神奇的操作,但是我不懂(手动狗头
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param n int整型
* @return long长整型
*/
long long dfs(long long t) {
if(t==1) return 1;
if(t==0) return 0;
return t+2*dfs(t/2);
}
long long Sum(int n) {
// write code here
long long ans = n;
ans+=2*dfs(n/2);
return ans;
}
};