牛客算法周周练2

牛客算法周周练2

题目链接

A

#include<bits/stdc++.h>
#define sc(x) scanf("%lld",&x);
#define pf printf
#define rep(i,s,e) for(int i=s;i<=e;i++)
#define dep(i,e,s) for(int i=e;i>=s;i--)
using namespace std;
typedef long long ll;
const int inf=~0u>>2;
const int maxn=1e5+7;
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int main()
{
	SIS;
	//¼ÓËÙcin/cout
	int n,k;
	cin>>n;
	k=n;
	int t=0;
	while(n)
	{
		int k=n%10;
		t = t*10+k;
		n=n/10;
	}
	cout<<k+t<<endl;
	return 0;
}

C

打个表出来,然后用lower_bound(返回第一个大于等于该元素的数)然后,计算个数,范围其实不大,注意查找得用二分,不然会TLE

代码:

#include<bits/stdc++.h>
#define sc(x) scanf("%lld",&x);
#define pf printf
#define rep(i,s,e) for(int i=s;i<=e;i++)
#define dep(i,e,s) for(int i=e;i>=s;i--)
using namespace std;
typedef long long ll;
const int inf=~0u>>2;
const int maxn=1e5+7;
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
ll b[maxn];
int main()
{
	SIS;
	//¼ÓËÙcin/cout
	for(ll i=1;i<=32000;i++)
	{
		b[i]=i*i;
	}
	int t;
	cin>>t;
	while(t--)
	{
		ll l,r;
		int pos1,pos2,flag1=0,flag2=0;
		cin>>l>>r;
		pos1=lower_bound(b,b+32000,l)-b;
		pos2=lower_bound(b,b+32000,r)-b;
		if(b[pos2]==r) pos2++;
		
	//	cout<<pos1<<endl<<pos2<<endl;
		cout<<pos2-pos1<<endl;		
	}
	return 0;
}

B

dp题,首先有个抽屉原理,当元素个数>=3600时直接输出YES了。
01背包。。
啊,不会dp呀。

假如:
2000 1000 3000
一开始2000加入的时候,2000%3600=2000,便标记dp[2000]为1
下次加入1000的时候遍历dp数组一遍,会发现dp[1600]为1,便在这个基础上加上a[i]再对3600取模(这里因为只要1600被标记了故v中只加入了(1000+1600)%3600=1000),结果存储在v数组中,最后再用将v数组中存储的放入dp数组中(dp[1000]=1),在标记(1000%3600=2600)dp[2600]=1;
这样我们可以发现会大大缩小枚举范围,比如很多组合加起来%3600都为4,在下一次加入时候,我们只要计算一次便可以得出结果是多少。

#include<bits/stdc++.h>
using namespace std;
int T,m,a[100005];//用于存储初始数据
int dp[3605];
int v[10000];暂存下余数
int main()
{
 
    scanf("%d",&T);
    while(T--)
    {
        memset(dp,0,sizeof(dp));
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=m&&!dp[0];i++)
        {
            int cnt=0;
            for(int j=1;j<3600;j++)
            {
                if(dp[j])//如果发现了之前计算保留的值
                {
                    v[cnt++]=(j+a[i])%3600;
                }
            }
            for(int j=0;j<cnt;j++)
            {
                dp[v[j]]=1;
            }
            dp[a[i]%3600]=1;
        }
        if(dp[0]) printf("YES\n");
        else printf("NO\n");
    }
 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值