2021牛客3

题目链接https://ac.nowcoder.com/acm/contest/11254#question

E - Math

题目

在这里插入图片描述

思路

打表找规律,可以看出
①(a,a3
②(i×i×i,i×i×i×i×i-i) 如:i=2时为:2,8,30

代码

#include <iostream>
#include <algorithm>
#define maxx 100000000
typedef long long ll;
using namespace std;
ll rec[maxx];
ll cnt=1;
void init()
{
    rec[cnt]=1;
    for(ll i=2; i<=1000000; i++)
    {
        __int128 x=i;
        __int128 y=i*i*i;
        while(y<=1000000000000000000)
        {
            cnt++;
            rec[cnt]=y;
            __int128 t=y;
            y=i*i*y-x;
            x=t;
        }
    }
    sort(rec+1,rec+cnt+1);
}


int main()
{
    int t;
    cin>>t;
    init();
    ll ans=0;
    while(t--)
    {
        ll x;
        cin>>x;
        ans=lower_bound(rec+1,rec+cnt+1,x)-rec-1;
        if(rec[ans+1]==x)
            ans++;
        cout<<ans<<"\n";
    }
    return 0;
}

总结

  1. 在计算y的时候,不能用ll,否则会溢出,得用__int128,是128位整数类型,但是无法使用cout和cin,得自己写函数
void scan(__int128 &x)//输入
{
    x = 0;
    int f = 1;
    char ch;
    if((ch = getchar()) == '-') f = -f;
    else x = x*10 + ch-'0';
    while((ch = getchar()) >= '0' && ch <= '9')
        x = x*10 + ch-'0';
    x *= f;
}
void print(__int128 x) //cout
{
    if(x < 0)
    {
        x = -x;
        putchar(-);
    }
     if(x > 9) print(x/10);
    putchar(x%10 +0);
}


vector<int> v;

void print()
{
    __int128_t x = 1100000000000000L;
    __int128_t y = 2200000000000000L;
    x*=y; //不能直接给x赋值为2420000000000000000000000000000。。。
    while(x)
    {
        v.push_back(x%10);
        x/=10;
    }

    reverse(v.begin(),v.end());
    for(int k=0; k<v.size(); k++)
        cout<<v[k];
}

int main()
{
    print();

    return 0;
}

  1. lower_bound的使用
    使用该函数在指定范围内查找某个目标值x时,最终查找到的结果y>=x,使用了二分查找

J - Counting Triangles

题目

就是给出每个边的颜色0或1,然后找三遍颜色一样的三角形

思路

一直在想着怎么搜索,其实,是一道排列组合的题,害〒▽〒
可以发现不满足条件的三角形一定是有两条边颜色不同的,所以只要把全部的情况-(两条边颜色不同的/2)就可以了…

代码

#include <bits/stdc++.h>
#define ri  int

typedef int lll;
typedef long long ll;
using namespace std;

const ll mod=1000000007;
const ll inf=999999999;

const ll N=5e3+5;

namespace GenHelper
{
    unsigned z1,z2,z3,z4,b,u;
    unsigned get()
    {
        b=((z1<<6)^z1)>>13;
        z1=((z1&4294967294U)<<18)^b;
        b=((z2<<2)^z2)>>27;
        z2=((z2&4294967288U)<<2)^b;
        b=((z3<<13)^z3)>>21;
        z3=((z3&4294967280U)<<7)^b;
        b=((z4<<3)^z4)>>12;
        z4=((z4&4294967168U)<<13)^b;
        return (z1^z2^z3^z4);
    }
    bool read() {
      while (!u) u = get();
      bool res = u & 1;
      u >>= 1; return res;
    }
    void srand(int x)
    {
        z1=x;
        z2=(~x)^0x233333333U;
        z3=x^0x1234598766U;
        z4=(~x)+51;
      	u = 0;
    }
}
bool edge[8005][8005];
int main() {
  ll n, seed;
  cin >> n >> seed;
  GenHelper::srand(seed);
  for (int i = 0; i < n; i++)
    	for (int j = i + 1; j < n; j++)
    	{
    		edge[j][i] = edge[i][j] = GenHelper::read();
		}
        	
        	
    ll ans=n*(n-1)*(n-2)/6;
    ll now=0;
    for(ri i=0;i<n;i++)
    {
    	now=0;
    	for(ri j=0;j<n;j++)
    	{
    		if(i!=j)
    		{
    			if(edge[i][j]) ++now;
			}
		}
        ans-=now*(n-1-now)/2;
	}
	cout << ans << '\n';
 	return 0;
}


总结

搜索超时的题,一定有简单的方法解决,而不是改进算法,以前也没有做过排列组合的题,涨知识惹

F - 24dian

题目

n个数字和加减乘除,通过任意组合,得到m
限制:
find all the possible set of cards that has a valid solution but any solution involves fraction(小数) in the calculation

思路

  1. 必须有小数,但结果是整数,所以n<4的时候,是不可能的,结果为0,所以只需要靠考虑n=4的情况
  2. 结果要升序排,所以在找答案的时候,循环中要求升序
  3. dfs的写法,尤其是小数的判断

代码

#include <bits/stdc++.h>
#define maxx 100050
using namespace std;

int n,m,cnt;
vector<double> vd;
vector<int> vi,ans[maxx];

int solve(vector<double> vd)
{
    if(vd.size()==1)
    {
        if(fabs(vd[0]-m)<1e-9)
            return 2;
        return 0;
    }

    int x=0;

    for(int i=0; i<vd.size(); i++)
    {
        for(int j=i+1; j<vd.size(); j++)
        {
            vector<double> tmp;
            tmp.clear();//
            for(int k=0; k<vd.size(); k++)
            {
                if(k!=i && k!=j)
                    tmp.push_back(vd[k]);
            }
            //+
            tmp.push_back(vd[i]+vd[j]);
            x=max(x,solve(tmp));
            if(x==2)
                return 2;
            //-,减法不满足交换律,有两种情况
            tmp.pop_back();
            tmp.push_back(vd[i]-vd[j]);
            x=max(x,solve(tmp));
            if(x==2)
                return 2;
            tmp.pop_back();
            tmp.push_back(vd[j]-vd[i]);
            x=max(x,solve(tmp));
            if(x==2)
                return 2;
            //*
            tmp.pop_back();
            tmp.push_back(vd[i]*vd[j]);
            x=max(x,solve(tmp));
            if(x==2)
                return 2;
            // 必须出现小数,要注意分母不能为0
            tmp.pop_back();
            if(fabs(vd[i])>1e-9)
            {
                tmp.push_back(vd[j]/vd[i]);
                int f=2;
                if(vd[j]/vd[i]-floor(vd[j]/vd[i]+1e-8)>1e-9)
                    f=1;
                x=max(x,min(f,solve(tmp)));
                if(x==2)
                    return 2;
                tmp.pop_back();
            }
            if(fabs(vd[j])>1e-9)
            {
                tmp.push_back(vd[i]/vd[j]);
                int f=2;
                if(vd[i]/vd[j]-floor(vd[i]/vd[j]+1e-8)>1e-9)
                    f=1;
                x=max(x,min(f,solve(tmp)));
                if(x==2)
                    return 2;
            }
        }
    }
    return x;
}


int main()
{
    cin>>n>>m;
    if(n<4)
    {
        cout<<0<<endl;
        return 0;
    }
    for(int i=1; i<=13; i++)
    {
        for(int j=i; j<=13; j++)
        {
            for(int k=j; k<=13; k++)
            {
                for(int l=k; l<=13; l++)
                {
                    vi.clear();
                    vd.clear();

                    vi.push_back(i),vd.push_back(i);
                    vi.push_back(j),vd.push_back(j);
                    vi.push_back(k),vd.push_back(k);
                    vi.push_back(l),vd.push_back(l);
                    if(solve(vd)==1)
                        ans[cnt++]=vi;
                }
            }
        }
    }
    cout<<cnt<<endl;
    for(int i=0; i<cnt; i++)
    {
        for(int j=0; j<ans[i].size(); j++)
            cout<<ans[i][j]<<' ';
        cout<<endl;
    }
    return 0;
}

总结

  1. double的比较
    相等: f a b s ( v d [ 0 ] − m ) < 1 e − 9 fabs(vd[0]-m) < 1e-9 fabs(vd[0]m)<1e9
    不为0: f a b s ( v d [ i ] ) > 1 e − 9 fabs(vd[i]) > 1e-9 fabs(vd[i])>1e9
    除数为小数: v d [ j ] / v d [ i ] − f l o o r ( v d [ j ] / v d [ i ] + 1 e − 8 ) > 1 e − 9 vd[j]/vd[i]-floor(vd[j]/vd[i]+1e-8) > 1e-9 vd[j]/vd[i]floor(vd[j]/vd[i]+1e8)>1e9

floor()向下取整,ceil()向上取整
这里要判断两个数相除是否为小数的时候,让x/y和floor(c/y)相减,如果差别不大,就说明是整数
比如:2.3-2=0.3,所以结果是小数

  1. 状态的转变:return 0表示完全不符合,return 2表示结果是符合的,但没有小数出现,return 1表示结果符合且小数出现,使用max和min函数来判断状态

  2. 题目本身注意:相减不满足交换律,有两种情况;相除有两种情况,且分母不能为0

B - Black and White

题目

n×m的网格,把每一个网格涂成黑色需要花费c(i,j),问怎么涂花费最小
其中,对于2×2的网格来说,如果有三个是黑色的,那么最后一个没有任何花费

思路

这个题竟然是一个最小生成树的题!
如果已经涂完色,就属于一个连通分量,加上要结果最小。。
不同之处是涂完三个最后一个不用图,通过找规律可得,需要涂n+m-1个方块,然后用prim或者kruscal都可以
不过具体怎么写也是第一次见到。。
分成j>=n 和 j<n,分别表示横向和纵向的最短路径,用dis[n*2]就可以表示

代码

#include<bits/stdc++.h>
using namespace std;

const int N=5005;
int cost[N][N];
int dis[2*N],vis[2*N];
ll n,m,a,b,c,d,p;
ll A;
int main()
{
	cin>>n>>m>>a>>b>>c>>d>>p;
	A=a;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			A=(A*A*b+A*c+d)%p;
			cost[i][j]=A; 
		}
	}
	for(int i=1;i<=n+m;i++)
	{
		dis[i]=1e9;
	}
	dis[1]=0;
	ll ans=0;
	for(int i=1;i<=n+m;i++)
	{
		int mn=1e9,pos=0;
		for(int j=1;j<=n+m;j++)
		{
			if(!vis[j]&&dis[j]<mn)
			{
				mn=dis[j];
				pos=j;
			}
		}
		vis[pos]=1;
		ans+=dis[pos];
		if(pos<=n)
		{
			for(int j=n+1;j<=n+m;j++)
			{
				dis[j]=min(dis[j],cost[pos][j-n]);
			}
		}
		else if(pos>n)
		{
			for(int j=1;j<=n;j++)
			{
				dis[j]=min(dis[j],cost[j][pos-n]);
			}
		}
	}
	printf("%lld",ans);
	return 0;
}

/*

3 4 4 5 6 7 50
11 28 45 2
39 46 13 30
37 24 31 48

*/

总结

在这里插入图片描述
这就是题解吗,i了i了。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本项目是一个基于SpringBoot开发的华府便利店信息管理系统,使用了Vue和MySQL作为前端框架和数据库。该系统主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的Java学习者,包含项目源码、数据库脚本、项目说明等,有论文参考,可以直接作为毕设使用。 后台框架采用SpringBoot,数据库使用MySQL,开发环境为JDK、IDEA、Tomcat。项目经过严格调试,确保可以运行。如果基础还行,可以在代码基础之上进行改动以实现更多功能。 该系统的功能主要包括商品管理、订单管理、用户管理等模块。在商品管理模块中,可以添加、修改、删除商品信息;在订单管理模块中,可以查看订单详情、处理订单状态;在用户管理模块中,可以注册、登录、修改个人信息等。此外,系统还提供了数据统计功能,可以对销售数据进行统计和分析。 技术实现方面,前端采用Vue框架进行开发,后端使用SpringBoot框架搭建服务端应用。数据库采用MySQL进行数据存储和管理。整个系统通过前后端分离的方式实现,提高了系统的可维护性和可扩展性。同时,系统还采用了一些流行的技术和工具,如MyBatis、JPA等进行数据访问和操作,以及Maven进行项目管理和构建。 总之,本系统是一个基于SpringBoot开发的华府便利店信息管理系统,使用了Vue和MySQL作为前端框架和数据库。系统经过严格调试,确保可以运行。如果基础还行,可以在代码基础之上进行改动以实现更多功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值