牛客小白月赛50

1.跳跃

链接:登录—专业IT笔试面试备考平台_牛客网

直接判断前后是否有刺激跳跃即可

#include<iostream>
 
using namespace std;
 
const int N=100010;
int a[N];
 
int main()
{
    int n,k;
    int cnt=0;
    cin >> n >> k;
    for(int i = 1; i <= n; i ++)
    {
        cin >> a[i];
    }
     
    for(int i = 2; i <= n ;i ++)
    {
        if(a[i]>a[i - 1]*k||a[i]*k<a[i - 1])//判断前后
            cnt ++;
    }
    cout << cnt;
}

 2.减法和除法

链接:登录—专业IT笔试面试备考平台_牛客网

每次判断哪个操作更小就选哪个

#include<iostream>
 
using namespace std;
typedef long long ll;
 
int main()
{
    ll n,x;
    cin  >> n >> x;
    ll cnt = 0;
    while(n>0)
    {
        if(n/2<n-x)//判断哪个更小
            n=n/2;
        else
            n-=x;
        cnt ++;
    }
    cout << cnt;
}

3.减法和求余

登录—专业IT笔试面试备考平台_牛客网

原本以为这道题只需要对2取余就好了,如果有大于2的数,全部取余为一次操作,剩下如果有数不为0只会是一,还需要一次操作,是零则不需要,但是忽略了一种数据即最大公约数不为1,像11,22,33,44,55,66,77,它们可以通过一次取余变为0,而像我之前那样想就会有两次操作,所以需要特判一下

#include<iostream>
#include<algorithm>
 
using namespace std;
 
const int N=100010;
typedef long long ll;
ll a[N];

int gcd(int a,int b)
{
    return b?gcd(b,a%b):a;
}
 
int main()
{
    int n;
    cin>>n;
    ll cnt=0;
    for(int i = 1; i <= n; i ++)
    {
        scanf("%lld",&a[i]);
    }
    
    ll d=a[1];
    for(int i = 1; i <= n; i ++)
    {
         d=gcd(d,a[i]);
    }
    
    if(d>1)//特判
    {
        cout<<"1";
        return 0;
    }
    sort(a + 1, a +1+ n);
       for(int i=1;i<=n;i++)
       {
            if(a[i]>=2)//有大于的就取余,算一次操作
           {
               for(int j=i;j<=n;j++)
                      a[j]=a[j]%2;
                cnt++;
           }
           else
               continue;
       }
    for(int i=1;i<=n;i++)
        if(a[i]!=0)//剩下的数中还有1
        {
             cout<<cnt+1<<endl;
             return 0;
        }
    cout<<cnt<<endl;
}

4.生日 

登录—专业IT笔试面试备考平台_牛客网

根据题意,总方案数是2^n,因为每个人都可以选择过或者不过。在第 i 天过生日的人有可能是第 i 个人,可能是第 i * 2 个人, 也可能是第 i * 2 + 1 个人,所以会有四种组合方式,若这三天都在n的范围内,则确定了三个人是否选择,还剩下2 ^(n-3)种方案,若 i * 2 + 1 不在范围内,则只会确定两个人是否选择,剩下 2^ (n-2)种方案,如果n>i,一种方案也没有。

#include <iostream>
#include <algorithm>

using namespace std;

typedef long long ll;
const int N = 1e5 + 10;
const ll MOD = 1e9 + 7;

int n;
ll a[N];
ll p2[N]; // 预处理 2 ^n

int main() 
{
	scanf("%d", &n);
	for (int i = 1; i <= n; i ++) 
		scanf("%lld", &a[i]);
    
	p2[0] = 1;
	for (int i = 1; i <= n ; i++) 
		p2[i] = (p2[i - 1] * 2ll) % MOD;
    
	ll res = 0;
	for (int i = 1; i <= n; i++) 
    {
		if (n < 2 * i) //0方案
			break;
		else if (n < 2 * i + 1) //确定2个
        {
			res = res + p2[n - 2] * (a[i] ^ a[2 * i]) % MOD;
			res %= MOD;
		} 
        else //确定三个
        {
            //四种组合方式:12 13 23 123
			res = res + p2[n - 3] * ((a[i] ^ a[2 * i]) + (a[i] ^ a[2 * i + 1]) + (a[2 * i + 1] ^ a[2 * i]) + (a[i] ^ a[2 * i] ^ a[2 * i + 1])) % MOD;
			res %= MOD;
		}
	}
	printf("%lld", res);
	return 0;
}

5.工艺品

登录—专业IT笔试面试备考平台_牛客网

这道题我一直在推公式,改了好多次只过了80的样例,结束后看别人的代码发现超简单,然后看题解发现只要按照这个

1.a<=c:鸡尾酒一直在加工

2.a>c:  尽可能多的加工玥玥加工的半成品。

来看就行了,那么能够加工的半成品是cnt = (n-c)/max(b,c),n - c是因为如果在最后小于c的时间内加工完 b 不能作为成品,所以要预留时间,那么总成品为(n-cnt*c)/a

#include<iostream>
  
using namespace std;
typedef long long ll;
  
int main()
{
    ll n,a,b,c;
    cin >> n >> a >> b >> c;
    if(a <= c)
        cout << n / a;
    else
    {
        int cnt = (n - c) / (max(b,c));
        cout << (n - cnt * c) / a + cnt;
    }
}

6.鸡尾酒数

登录—专业IT笔试面试备考平台_牛客网

找规律可以发现

个位数没有鸡尾酒数

十位数每十个数可凑出一次鸡尾酒数(19,28,37.....)

百位数每十个数可凑出一次鸡尾酒数

\vdots

当位数为 n 时,记前 n 位数的和为 last,last 的最后一位一定在0~9范围内,则最后以为填0~9十个数中某一个一定可以凑出鸡尾酒数,所以1~n 的鸡尾酒数初步计算为 n/10-1 个,如果 n 为1231,会有1231/10=123个鸡尾酒数,但如果n=1235,1235/10=123,但实际上有124个鸡尾酒数,所以最后需要特判一下。

上述思路为 n / 10 - 1特判最后是否加一,而下面代码则是判断 n/10 是否需要减一

#include<cstring>
#include <iostream>
#include <cmath>
#include <algorithm>

using namespace std;

//const int mod=1e9+7;
const int MAXN = 1e6;
using ll = long long ;
ll n, q;
char s[MAXN];
ll pre[MAXN];
const ll mod = 1e9 + 7;
 
ll check(ll d, ll lst) 
{
	if (n == 1 || lst >= 10 - d || d == 0)
		return 0;
	return 1;
}
 
int main() 
{
	scanf("%s %lld", s + 1, &q);
	n = (ll)strlen(s + 1);

	pre[1] = 1;
	for (int i = 2; i <= n+1 ; i++) //10^n
    {
		pre[i] = pre[i - 1] * 10 % mod;
	}

	ll dsum = 0, ans = 0;
    //ans记录题目中的n/10是多少
	for (int i = 1; i <= n - 1; i++) 
    {
		dsum += (s[i] - '0');//数位和
		ans = (ans * 10ll + (ll)(s[i] - '0')) % mod;
	}
	printf("%lld\n", (ans - check(dsum % 10, s[n] - '0') + mod) % mod);

	int a, b;
	while (q--) 
   {
		scanf("%d %d", &a, &b);
		if (a != n) //这一位变成0带来的影响
        {
			dsum -= s[a] - '0';
			ans = (ans - pre[n - a] * (ll)(s[a] - '0') + mod) % mod;
		}
		s[a] = (b + '0');
		if (a != n)//这一位+b带来的影响
        {
			dsum += b;
			ans = (ans + pre[n - a] *(ll) b) % mod;
		}
		printf("%lld\n", (ans - check(dsum % 10, s[n] - '0') + mod) % mod);
	}
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值