2019腾讯暑假实习提前批题目

腾讯暑假实习提前批A题 ******贪心

题意:
牛家村的货币是一种很神奇的连续货币。

他们货币的最大面额是n,并且一共有面额为1,面额为2…面额为n,n种面额的货币。

牛牛每次购买商品都会带上所有面额的货币,支付时会选择给出硬币数量最小的方案。

现在告诉你牛牛将要购买的商品的价格,你能算出牛牛支付的硬币数量吗? (假设牛牛每种面额的货币都拥有无限个。)

输入格式
共一行,包含两个整数n和m,分别表示货币的最大面额以及商品的价格。

输出格式
一个整数表示牛牛支付的硬币数量。

数据范围
1≤n≤105,
1≤m≤109
输入样例1:
6 7
输出样例1:
2
输入样例2:
4 10
输出样例2:
3

思路:其实就是一个简单的贪心,每次为了凑足m元钱,去[1-n]的面额里面,取最大的n面额去凑就可以使硬币数量最小

*代码

#include <iostream>

using namespace std;

int main() {
    
    
  int n, m, res;
  cin >> n >> m;
  res = (m + n - 1) / n;//(m/n)向上取整
  cout << res << endl;
}

腾讯暑假实习提前批B题 ********规律

妞妞最近迷上了王者荣耀。

小Q得到了一个奇妙的数列,这个数列有无限多项,数列中的第 i 个数字为i∗(−1)i,比如数列的前几项为-1,2,-3,4,-5…

小Q兴奋把这个数列拿去给妞妞看,并希望借此邀请妞妞吃饭。

妞妞想了想,对小Q说:“对于这个数列,我每次询问你一个区间,你在1秒内把这个区间里的数字的和告诉我,如果你答得上来我就跟你一起去吃饭。”

由于妞妞最近沉迷王者荣耀,已经很久都没理过小Q了,所以小Q不想失去这次珍贵的机会,你能帮帮他吗?

输入格式
第一行,一个整数 q,表示妞妞的询问次数。

接下来 q 行,每行两个整数 l 和 r,表示妞妞询问的区间的左端点和右端点。

输出格式
共 q 行,每行一个整数,表示妞妞询问的区间和。

数据范围
1≤q≤105,
1≤l≤r≤109
输入样例1:
4
2 4
2 2
3 3
1 5
输出样例1:
3
2
-3
-3
输入样例2:
1
1 1000000000
输出样例2:
500000000

*思路:在这里插入图片描述如图所示:当我把整个序列俩俩配成一对,就可以出现1,2俩种情况。第2种情况很好理解,假设答案是res, 这个序列被分成K对,留下最后一个数R, 当是L是奇数时 ,每对的和是1,所以res = res + K + R, 当L是偶数时,每对的和是-1,res = res + (-K)+ R ;第一种情况不用加最后一个数,其他部分和第一种情况相同。

*代码

#include <iostream>

using namespace std;

int main() {
    
    
  int q;
  cin >> q;
  while(q -- ) {
    
    
    int res = 0, l, r;
    cin >> l >> r;
    int k = (r - l + 1) >> 1;
    if(l & 1) res += k;
    else res += (-k);
    if((r - l + 1) & 1) {
    
    
      if(r & 1) res += (-r);
      else res += r;
    }
    cout << res << endl;
  }
  return 0;
}

腾讯暑假实习提前批C题 ******* 线性筛求阶乘

小Q和牛妹参加一个剪刀石头布的游戏,游戏用卡片来玩,每张卡片是剪刀,石头,布中的一种,每种类型的卡片有无限个。

牛妹从中选了n张卡片排成一排,正面朝下,小Q也会选择n张卡片排成一排,然后小Q和牛妹的卡片会依次进行比对,第一张对第一张,第二张对第二张…

如果小Q赢,小Q会得到一分,现在已知牛妹的每一张牌以及小Q最终的得分 s,请问小Q有多少种选择卡片的方案(多少不同的排列)

输入格式
第一行包含两个整数 n 和 s。

第二行包含 n 个整数,表示牛妹的每张卡片,每个数在[0,2]之间,0代表石头,1代表布,2代表剪刀。

输出格式
输出一个整数,表示总方案数对109+7取模后的值。

数据范围
1≤n≤2000,
0≤s≤2000
输入样例:
3 2
0 1 2
输出样例:
6

*思路:在这里插入图片描述

如图所以当输入n, s时,答案我们只要在n个位置选s个位置的动作赢然后乘上(n - s)个位置选平和输的动作就不会加分。所以答案就是res = C(n, s) * (2^(n-s)) , 难点在于怎么求组合数,因为n有2000多,我们可以线性筛c(n, s)=(n!)/((s!)*(n-s)!) ,求出分子和分母所有质因素的数目,然后相加减,就可以把除法换成乘法。不会超时咯。

#include <iostream>

using namespace std;
const int MOD = 1e9 + 7;
const int N = 2010;
typedef long long LL;
int primes[N], cnt, a[N], powers[N];
bool st[N];

void get_primes(int n)
{
    
    
    for (int i = 2; i <= n; i ++ )
    {
    
    
        if (!st[i]) primes[cnt ++ ] = i;
        for (int j = 0; j < cnt && i * primes[j] <= n; j ++ )
        {
    
    
            st[primes[j] * i] = true;
            if (i % primes[j] == 0) break;
        }
    }
}

int get(int n, int p) {
    
    
  int s = 0;
  while(n > 0) {
    
    
    s += n / p;
    n /= p;
  }
  return s;
}
int main() {
    
    
  int n, s;
  cin >> n >> s;
  for(int i = 0; i < n; i++) cin >> a[i];
  if(s > n) {
    
    
    cout << "0" << endl;
  }
  else {
    
    
    get_primes(n);
    for(int i = 0; i < cnt; i++) {
    
    
      int p = primes[i];
      powers[i] = get(n, p) - get(s, p) - get(n - s, p);
    }
    int res = 1;
    for(int i = 0; i < cnt; i++) {
    
    
      int p = primes[i];
      while(powers[i] -- ) res = (1LL) * res * p % MOD;
    }
    for(int i = 0; i < n - s; i++) res = res * 2 % MOD;
    cout << res << endl;
  }
  return 0;
}

腾讯暑假实习提前批D题 ********** 滑动窗口(双指针法)

小Q在进行射击气球的游戏,如果小Q在连续T枪中打爆了所有颜色的气球,将得到一只QQ公仔作为奖励。(每种颜色的球至少被打爆一只)。

这个游戏中有m种不同颜色的气球,编号1到m。

小Q一共有n发子弹,然后连续开了n枪。

小Q想知道在这n枪中,打爆所有颜色的气球最少用了连续几枪?

输入格式
第一行包含两个整数n和m。

第二行包含n个整数,分别表示每一枪打中的气球的颜色,0表示没打中任何颜色的气球。

输出格式
一个整数表示小Q打爆所有颜色气球用的最少枪数。

如果小Q无法在这n枪打爆所有颜色的气球,则输出-1。

数据范围
1≤n≤106,
1≤m≤2000
输入样例:
12 5
2 5 3 1 3 2 4 1 0 5 4 3
输出样例:
6
样例解释
有五种颜色的气球,编号1到5。

游客从第二枪开始直到第七枪,这连续六枪打爆了5 3 1 3 2 4这几种颜色的气球,包含了从1到5的所有颜色,所以最少枪数为6。

*思路:在这里插入图片描述如图:用俩个指针维护L,R维护M种气球的区间, 求最小区间值。刚开始R++(红色箭头),当不是0号气球时并且i号气球第一次出现M++,一直到区间有M种气球时,判断当前气球数在区间有多个时或者为0号气球时,L++(绿色箭头)。更新最小区间。

#include <iostream>
#include <cstdio>

using namespace std;
const int N = 1000010;
int c[N], s[N];

int main() {
    
    
  int n, m;
  scanf("%d%d", &n, &m);
  for(int i = 1; i <= n; i++) scanf("%d", &c[i]);
  int colors = 0, res = n + 1;
  for(int R = 1, L = 0 ; R <= n; R++) {
    
    
    if(c[R] && !s[c[R]]) colors++;
    s[c[R]] ++;
    if(colors == m) {
    
    
      while(s[c[L]] > 1 || !c[L]) {
    
    
        s[c[L]] --;
        L++;
      }
      res = min(res, R - L + 1);
    }
  }
  if(res == n + 1) printf("-1\n");
  else printf("%d\n", res);
  return 0;
}

*用来学习交流,O(∩_∩)O散花~

猜你喜欢

转载自blog.csdn.net/woshi222B/article/details/88984066
今日推荐