0
点赞
收藏
分享

微信扫一扫

2022牛客寒假算法基础集训营6(补题)

芷兮离离 2022-02-13 阅读 65
算法c++

唉现在还是只能做比赛里的部分模拟题,,,涉及算法的还是搞不定wwww

I - A+B问题

思路: 模拟加法。

AC代码:

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define INF 0x3f3f3f3f
//判断是否需要开ll!!!
//判断是否需要初始化!!!
const int mod=1e9+7;
const int N=1e6;
int k,s[N],A[N],B[N];
string a,b;

int main()
{
//	freopen("test.in","r",stdin);
//  freopen("output.in", "w", stdout);
    cin>>k;
    cin>>a>>b;
    int tot1=0,tot2=0;
    for(int i=a.length()-1;i>=0;i--)
    A[++tot1]=a[i]-'0';
    for(int i=b.length()-1;i>=0;i--)
    B[++tot2]=b[i]-'0';
    int ss=0;
    int cnt=0;
    for(int i=1;i<=max(tot1,tot2);i++)
    {
    	s[++cnt]=(A[i]+B[i]+ss)%k;
    	ss=(A[i]+B[i]+ss)/k;
	}
	while(ss)
	{
		s[++cnt]=ss%k;
		ss=ss/k;
	}
	for(int i=cnt;i>=1;i--)
	cout<<s[i];
	cout<<'\n';
	return 0;
}

F - +-串

思路: 要保证结果的绝对值最小,应保证+,-号差值尽可能小,所以对于每一次k的使用分类讨论即可。

AC代码:

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define INF 0x3f3f3f3f
//判断是否需要开ll!!!
//判断是否需要初始化!!!
const int mod=1e9+7;
int t,k,a[3];
string s;

int main()
{
//	freopen("test.in","r",stdin);
//  freopen("output.in", "w", stdout);
    cin>>t;
    while(t--)
    {
    	memset(a,0,sizeof(a));
    	cin>>s;
    	cin>>k;
    	int len=s.length();
    	for(int i=0;i<len;i++)
    	{
    		if(s[i]=='+') a[1]++;
    		else a[2]++;
		}
		while(k)
		{
			if(a[1]>a[2])
			{
				a[2]++,a[1]--;
				k--;
			}
			else if(a[2]>a[1])
			{
				a[2]--,a[1]++;
				k--;
			}
			else if(a[1]==a[2])
			{
				a[1]--,a[2]++;
				k--;
			}
		}
		cout<<abs(a[1]-a[2])<<'\n';
	}
	return 0;
}

E - 骑士

思路: 结构体存每位骑士攻击力,防御力,生命值,及防御力和生命值的和,按照攻击力排序,遍历求每位骑士需要的生命药剂之和即可。

AC代码:

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define INF 0x3f3f3f3f
//判断是否需要开ll!!!
//判断是否需要初始化!!!
const int mod=1e9+7;
const int N=2e5+5;
int t,n;

struct node
{
	int a,b,h;
	int hurt; 
}e[N];

bool cmp(node a,node b)
{
	if(a.a>b.a) return true;
	else return false;
}

int main()
{
//	freopen("test.in","r",stdin);
//  freopen("output.in", "w", stdout);
    scanf("%d",&t);
    while(t--)
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    	{
    		e[i].a=0,e[i].b=0;
    		e[i].h=0,e[i].hurt=0;
		}
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].h);
    		e[i].hurt=e[i].b+e[i].h;
		}
		sort(e+1,e+1+n,cmp);
		ll ans=0;
		for(int i=1;i<=n;i++)
		{
			if(i==1&&e[i+1].a>=e[i].hurt) 
			{
				ans+=(e[i+1].a-e[i].hurt+1);
			}
			else if(i!=1)
			{
				if(e[1].a>=e[i].hurt)
				ans+=(e[1].a-e[i].hurt+1);
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}

os:一直卡TLE,改了输入输出,改了初始化方法才好的,,,罚时+++

D - 删除子序列

思路: 遍历T,给每一位编号;遍历S,统计最多可以删去T的数量。

AC代码:

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define INF 0x3f3f3f3f
//判断是否需要开ll!!!
//判断是否需要初始化!!!
const int mod=1e9+7;
const int N=28;
int st,n,m;
string s,t;

struct node
{
	int num;
	char c;
} e[N];

int main()
{
//	freopen("test.in","r",stdin);
//  freopen("output.in", "w", stdout);
    scanf("%d",&st);
    while(st--)
    {
    	memset(e,0,sizeof(e));
    	scanf("%d%d",&n,&m);
    	cin>>s>>t;
    	for(int i=0;i<m;i++)
    	{
    		e[i].c=t[i];
		}
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<m;j++)
			{
				if(j==0&&s[i]==e[j].c) e[j].num++;
				else if(j!=0&&s[i]==e[j].c&&e[j-1].num>e[j].num) e[j].num++;
			}   //要保证删除T,顺序一定,计数加个条件即可满足题意
		}
		printf("%d\n",e[m-1].num);
	}
	return 0;
}

os:因为没有初始化WA了n发,太菜了,不过感觉这样比标解好做

B - 价值序列

思路: 标解:

AC代码:

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define INF 0x3f3f3f3f
//判断是否需要开ll!!!
//判断是否需要初始化!!!
const int mod=998244353;
const int N=1e5+5;
int t,n;
ll a[N];

ll pmod(ll a,ll b)
{
	ll res=1;
	while(b)
	{
		if(b&1) res=res*a%mod;
		b>>=1;
		a=a*a%mod;
	}
	return res;
} 

int main()
{
//	freopen("test.in","r",stdin);
//  freopen("output.in", "w", stdout);
    scanf("%d",&t);
    while(t--)
    {
    	memset(a,0,sizeof(a));
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    	scanf("%lld",&a[i]);
    	ll ans=1;
    	for(int i=1;i<=n;i++)
    	{
    		int j=i;
    		while(j<n&&a[j+1]==a[i]) j++;
    		if(i-1>=1&&j+1<=n&&(a[i-1]<a[i]&&a[j+1]>a[i]||a[i-1]>a[i]&&a[j+1]<a[i]))
    		ans=ans*pmod(2,j-i+1)%mod;
    		else ans=ans*(pmod(2,j-i+1)+mod-1)%mod;
    		i=j;
		}
		printf("%lld\n",ans);
	}
	return 0;
}

os:还是思维题,还需要锻炼

J - 牛妹的数学难题

思路: a[i]=0时,相乘结果为0,就可以用组合数判断k个数相乘有几个1,几个2,求所有非0情况的和即可。

AC代码:

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define INF 0x3f3f3f3f
//判断是否需要开ll!!!
//判断是否需要初始化!!!
const int mod=998244353;
const int N=1e7+5;
ll n,k;
ll func[N],a[N],b[4],inv[N],p2[N];

ll C(ll n,ll m)
{
	if(n<m) return 0;//注意特判!
	return func[n]*inv[m]%mod*inv[n-m]%mod;
}

int main()
{
//	freopen("test.in","r",stdin);
//  freopen("output.in", "w", stdout);
    func[0]=func[1]=inv[0]=inv[1]=1;
	for(int i=2;i<=N-5;i++)
	{
		func[i]=func[i-1]*i%mod;
		inv[i]=(mod-mod/i)*inv[mod%i]%mod;
	}
    for(int i=2;i<=N-5;i++)
    inv[i]=inv[i-1]*inv[i]%mod;
    p2[0]=1;
    for(int i=1;i<=N-5;i++)
    p2[i]=p2[i-1]*2%mod;
	scanf("%lld%lld",&n,&k);
    for(int i=1;i<=n;i++)
    {
    	scanf("%lld",&a[i]);
    	b[a[i]]++;
	}
	ll ans=0;
	for(int i=0;i<=k;i++)
	{
		ans=(ans+C(b[2],i)*p2[i]%mod*C(b[1],k-i)%mod)%mod;
	}
	printf("%lld\n",ans);
	return 0;
}

os:注意求组合数的方法!除了使用费马小定理快速幂求,也可以这样预处理求。

若有错误请指教orzorz

举报

相关推荐

0 条评论