牛客小白月赛5(回顾补题)

官方题解

A 无关(relationship)

没想到容斥原理,一开始想使用线性筛晒出符合条件的数字,然后超内存。之后尝试想到容斥原理,当时容斥原理不会枚举两辆数字相乘,三三数字相乘这些情况所以没写。代码能力还是太弱了。

B 范围(range)

这个赛后看题解补完了。

#include<bits/stdc++.h>
using namespace std;
int main() {
    int A,B;
    cin>>A>>B;
    double sum1=4*A*A-8*(A*A-B);
    if(sum1>=0) {
        double ans1=(2*A+sqrt(sum1))/4,ans2=(2*A-sqrt(sum1))/4;
        printf("%.2lf %.2lf\n",min(ans1,ans2),max(ans1,ans2));
    } else
        puts("No Answer");
    return 0;
}

C 水题(water)

函数f可以枚举几项后找出规律,发现为斐波那契数列。N皇后问题由于最多只有13,所以打表解决,至于如何判定是否为斐波那契数,由于符合x范围的只存在前90项,所以枚举查找即可得出答案。至于如何求取m进制下n!末尾0的个数,CodeForce上有过原题,转载一下

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int MAXN=101;
int num[20];
long long num1[MAXN];
void init() {
	num[1]=1,num[2]=0,num[3]=0;  
	num[4]=2,num[5]=10,num[6]=4;  
	num[7]=40,num[8]=92,num[9]=352;
	num[10]=724,num[11]=2680,num[12]=14200,num[13]=73712;
	
	num1[1]=1,num1[2]=1;
	for(int i=3;i<=88;i++)
		num1[i]=num1[i-1]+num1[i-2];
}
int main() {
	init();
	long long x,m;
	cin>>x>>m;
	bool flag=false;
	for(int i=1;i<=88;i++) {
		if(x==num1[i]) {
			flag=true;
			break;
		}
	}
	if(flag) {
		long long ans=1e18,sum1=0,sum2=0;
        for(int i=2;i<=100;i++) {
            if(m%i) 
				continue;
            sum1=sum2=0;
            //sum1记录m中包含质因数i的个数 
            while(m%i==0) 
				sum1++,m/=i;
            long long temp=x;
            //sum2记录x!中包含质因数i的个数
            while(temp) {
                sum2+=temp/i;
				temp/=i;
			}
			//由于求解在m进制下最小的质因数的个数,所以x!中包含的
			//质因数的数目需要减去m中包含的质因数的数目
			//最后的结果才是答案 
            ans=min(ans,sum2/sum1);
        }
        printf("%lld\n",ans);
	} else
		cout<<num[x%min((long long)13,m)+1]<<endl;
	return 0;
}

D 阶乘(factorial)

纯粹考虑代码能力的一道题目,分块的思想。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll func(ll n,ll c){
    ll b=((n/c)*((n/c)-1))/2*c;
    return b+(n%c+1ll)*(n/c);
}
int main(){
    ll n, k=5, ans=0;
    scanf("%lld",&n);
    while((n/k)>=1) 
		ans+=func(n, k),k*=5ll;
	printf("%lld\n",ans);
    return 0;
}

F 圆(circle)

这个果断OESQ上找出序列然后直接抄一波结论得出答案啦。(不过同样代码第一发竟然会WA就很迷,之后倒是对了)

#include<bits/stdc++.h>
int main()
{
    long long n;
    while(~scanf("%lld",&n)) {
        long long ans=(n*n*n*n - 6*n*n*n + 23*n*n - 18*n + 24)/24;
        printf("%lld\n",ans);
    }
    return 0;
}

G 异或(xor)

发现样例中的数字是斐波那契数列,同时斐波那契数列中数字为偶数不吃,奇数直接吃,那就盲猜一波结论然后莽一发吧然后就过了......

#include<bits/stdc++.h>
using namespace std;
int main() {
    long long n;
    while(~scanf("%lld",&n)) {
        long long ans1=n/3*2,ans2=n%3;
        printf("%lld\n",ans1+ans2);
    }
    return 0;
}

H 最大公约数(lcm)

真签到题

#include<bits/stdc++.h>
using namespace std;
int main() {
    unsigned long long a,b;
    cin>>a>>b;
    unsigned long long c=__gcd(a,b);
    cout<<(a/c)*b<<endl;
    return 0;
}

I 区间 (interval)

看到区间问题---线段树线段树。然后MLE,树状数组树状数组,然后AC。当然正解是前缀和啦。前缀和

树状数组

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 1000101;
ll c1[MAXN],c2[MAXN],num[MAXN];
int n,m;
ll lowbit(ll x)
{
    return (x & (-x));
}
ll sigma(ll a[],ll pos)
{
    ll ans = 0;
    while(pos)
    {
        ans += a[pos];
        pos -= lowbit(pos);
    }
    return ans;
}
 
void add(ll a[],int pos, ll num)
{
    while(pos < MAXN)
    {
        a[pos] += num;
        pos += lowbit(pos);
    }
    return ;
}
int main()
{
	memset(c1,0,sizeof(c1));
	memset(c2,0,sizeof(c2));
	
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i++)
    {
        scanf("%lld",&num[i]);
        add(c1,i,num[i] - num[i-1]);
        add(c2,i,(i-1)*(num[i]-num[i-1]));
    }
    //首先进行区间的更新操作
    ll q,l,r,v;
    for(int i = 1;i <= m;i++)
    {
    	scanf("%lld%lld%lld%lld",&q,&l,&r,&v);
	    if(q==1) v=-v;
	    add(c1,l,v);add(c1,r+1,-v);
	    add(c2,l,v*(l-1));add(c2,r+1,-v*r);
	}
   
    //然后进行区间求和操作
    scanf("%lld%lld",&l,&r);
    ll sum1 = (l-1)*sigma(c1,l-1) - sigma(c2,l-1);
    ll sum2 = r *sigma(c1,r) - sigma(c2,r);
    printf("%lld\n",sum2 - sum1);
}

前缀和

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1000000;
int n,m,q,l,r,p;
int x[MAXN+11];
int c[MAXN+11];
int main()
{
    while(~scanf("%d%d",&n,&m)) {
        memset(c,0,sizeof(c));
        for(int i=1;i<=n;i++)
            scanf("%d",&x[i]);
        for(int i=1;i<=m;i++) {
            scanf("%d%d%d%d",&q,&l,&r,&p);
            if(q!=1)
                c[l]+=p,c[r+1]-=p;
            else
                c[l]-=p,c[r+1]+=p;
        }
        for(int i=1;i<=n;i++)
            c[i]+=c[i-1];
        scanf("%d%d",&l,&r);
        long long sum=0;
        for(int i=l;i<=r;i++)
            sum=sum+x[i]+c[i];
        printf("%lld\n",sum);
     }
     return 0;
}

J 时间(time)

又一道签到题。

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
struct node{
    int hour,mintue;
    int sum;
};
vector<node> p;
void init() {
    node temp;
    temp.hour=0,temp.mintue=0;
    temp.sum=temp.hour*60+temp.mintue;
    p.push_back(temp);
      
    temp.hour=1,temp.mintue=10;
    temp.sum=temp.hour*60+temp.mintue;
    p.push_back(temp);
      
    temp.hour=2,temp.mintue=20;
    temp.sum=temp.hour*60+temp.mintue;
    p.push_back(temp);
      
    temp.hour=3,temp.mintue=30;
    temp.sum=temp.hour*60+temp.mintue;
    p.push_back(temp);
      
    temp.hour=4,temp.mintue=40;
    temp.sum=temp.hour*60+temp.mintue;
    p.push_back(temp);
      
    temp.hour=5,temp.mintue=50;
    temp.sum=temp.hour*60+temp.mintue;
    p.push_back(temp);
      
    temp.hour=10,temp.mintue=1;
    temp.sum=temp.hour*60+temp.mintue;
    p.push_back(temp);
      
    temp.hour=11,temp.mintue=11;
    temp.sum=temp.hour*60+temp.mintue;
    p.push_back(temp);
      
    temp.hour=12,temp.mintue=21;
    temp.sum=temp.hour*60+temp.mintue;
    p.push_back(temp);
      
    temp.hour=13,temp.mintue=31;
    temp.sum=temp.hour*60+temp.mintue;
    p.push_back(temp);
      
    temp.hour=14,temp.mintue=41;
    temp.sum=temp.hour*60+temp.mintue;
    p.push_back(temp);
      
    temp.hour=15,temp.mintue=51;
    temp.sum=temp.hour*60+temp.mintue;
    p.push_back(temp);
      
    temp.hour=20,temp.mintue=2;
    temp.sum=temp.hour*60+temp.mintue;
    p.push_back(temp);
      
    temp.hour=21,temp.mintue=12;
    temp.sum=temp.hour*60+temp.mintue;
    p.push_back(temp);
      
    temp.hour=22,temp.mintue=22;
    temp.sum=temp.hour*60+temp.mintue;
    p.push_back(temp);
      
    temp.hour=23,temp.mintue=32;
    temp.sum=temp.hour*60+temp.mintue;
    p.push_back(temp);
      
    temp.hour=0,temp.mintue=0;
    temp.sum=24*60;
    p.push_back(temp);
}
int main() {
    init();
    int temp1,temp2;
    scanf("%d:%d",&temp1,&temp2);
    if(temp1==0&&temp2==0) {
        puts("23:32");
        puts("1:10");
        return 0;
    } else {
        int sum1=temp1*60+temp2;
        int min1=inf,ans=0;
        for(int i=0;i<p.size();i++) {
            if(p[i].sum<sum1) {
                if((sum1-p[i].sum)<min1)
                    min1=sum1-p[i].sum,ans=i;
            } else
                break;
        }
        cout<<p[ans].hour<<":"<<p[ans].mintue<<endl;
        for(int i=0;i<p.size();i++) {
            if(p[i].sum>sum1) {
                cout<<p[i].hour<<":"<<p[i].mintue<<endl;
                break;
            }
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值