AtCoder Beginner Contest 195

题目传送门

A.Health M Death

考试情况(题解)

水题,判断n能不能整除m即可

code
#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n,m;
	cin>>n>>m;
	if(m%n==0) cout<<"Yes";
	else cout<<"No";
	return 0;
}

B.Many Oranges

考试情况(题解)

一开始写了一个没有优化的暴力
果然T了
根据题意思考优化
通过一种方式,使第一次找到的值一定为最大值即可大大减少时间复杂度
从小到大(从大到小)枚举可能成立的橘子数量,内层暴力枚举是否能恰好使用这么多橘子满足题意即可

code
#include<bits/stdc++.h>
using namespace std;
bool f1[1000000];
int main()
{
	int a,b,w,maxn=-1,minn=1e9;
	bool f=0;
	cin>>a>>b>>w;
	w*=1000;
	int L=ceil(w*1.0/b),R=w/a;
	for(int i=L;i<=R;i++)
	{
		for(int j=0;j<=i;j++)
		{
			for(int k=a;k<=b;k++)
			{
				int x=k*j;
				int y=w-x;
				int z=y/k;
				if(z*y+k*j==w)
				{
					cout<<i<<' ';
					f=1;
					break;
				}
			}
			if(f==1) break;
		}
		if(f==1) break;
	}
	if(f==0)
	{
		cout<<"UNSATISFIABLE";
		return 0;
	}
	for(int i=R;i>=L;i--)
		for(int j=0;j<=i;j++)
			for(int k=a;k<=b;k++)
			{
				int x=k*j;
				int y=w-x;
				int z=y/k;
				if(z*y+k*j==w)
				{
					cout<<i;
					return 0;
				}
			}
	return 0;
}

C.Comma

考试情况

大致是一道数论题吧(或者是什么我也不知道)
总之被我的六行 if 给卡掉了
代码通俗易懂,带两组数据试试就可以理解了

code
#include<bits/stdc++.h>
using namespace std;
int main()
{
	long long n;
	cin>>n;
	if(n<1000) cout<<0;
	else if(n<=999999) cout<<n-999;
	else if(n<=999999999) cout<<n-999+n-999999;
	else if(n<=999999999999) cout<<n-999+n-999999+n-999999999;
	else if(n<=999999999999999) cout<<n-999+n-999999+n-999999999+n-999999999999;
	else cout<<n-999+n-999999+n-999999999+n-999999999999+1;
	return 0;
}

D.Shipping Center

考试情况

一道贪心题目,做dp做傻了,没敢去写这个贪心
另外也没注意到数据范围这么小!
所以…没写

题解

模拟题中的过程
有一个关键的点,每个箱子只能放一个物品!
可以利用贪心算法,先把物品按价值大小排序,然后把这个物品塞到能装下它的最小的箱子中
统计加起来的价值即可

#include<bits/stdc++.h>
using namespace std;
const int N=55;
int x[N],q[N],n,m,Q,l,r;
bool vis[N];
struct node
{
	int w,v;
}a[N];
bool cmp(node x,node y)
{
	return x.v>y.v;
}
int main()
{
	scanf("%d%d%d",&n,&m,&Q);
	for(int i=1;i<=n;i++) scanf("%d%d",&a[i].w,&a[i].v);
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=m;i++) scanf("%d",&x[i]);
	for(int i=1;i<=Q;i++)
	{
		memset(vis,0,sizeof(vis));
		scanf("%d%d",&l,&r);
		int tot=0;
		for(int j=1;j<=m;j++)
			if(j<l||j>r) q[++tot]=x[j];
		sort(q+1,q+1+tot);
		int ans=0;
		for(int j=1;j<=n;j++)
			for(int k=1;k<=tot;k++)
				if(!vis[k]&&a[j].w<=q[k])
				{
					ans+=a[j].v;
					vis[k]=1;
					break;
				}
		printf("%d\n",ans);
	}
	return 0;
}

E.Lucky 7 Battle

考试情况

不会

题解

这是一道属于dp的简单题
f [ i ] [ j ] f[i][j] f[i][j]表示前i位的值余数是否能为j
从后往前来推
初始化: f [ n ] [ 0 ] = 1 f[n][0]=1 f[n][0]=1
分别用 p p p q q q来表示题目中描述的两种方式:加空串和加一个数字的结果
如果是Takahashi进行选择,那么只要 p p p q q q有一个可以让结果为 7 7 7的倍数即可
但如果是让Aoki选择,只有 p p p q q q都可以让结果为 7 7 7,才能使当前结果成立
最后判断最开始的第 0 0 0位能否使 m o d 7 mod7 mod7的值恰好为 0 0 0即可

code
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
bool f[maxn][7];
int n;
string s,x;
int main() 
{
    cin>>n>>s>>x;
    f[n][0]=1;
    for(int i=n-1;i>=0;i--)
        for(int j=0;j<7;j++) 
		{
            bool p=f[i+1][10*j%7],q=f[i+1][(10*j+s[i]-'0')%7];
            if(x[i]=='T') f[i][j]=p|q;
            else f[i][j]=p&q;
        }
    if(f[0][0]) puts("Takahashi");
    else puts("Aoki");
    return 0;
}

F.Coprime Present

考试情况

不会

题解

通过一个重要的性质:辗转相除法!
g c d ( a , b ) = g c d ( a − b , b ) , ( a > b ) gcd(a,b)=gcd(a-b,b),(a>b) gcd(a,b)=gcd(ab,b),(a>b)
所以 g c d ( a , b ) ≤ ( B − A ) ≤ 72 gcd(a,b)\leq (B-A)\leq 72 gcd(a,b)(BA)72
因此a和b的最大公因数都是在 72 72 72以内的
答案集合包含 [ 1 , 72 ] [1,72] [1,72]范围的质因数每个最多出现一次
[ 1 , 72 ] [1,72] [1,72]的质数只有 20 20 20个,所以可以把这 20 20 20个数打表出来,用状压来解决此题
d p [ i ] dp[i] dp[i]表示状态i的质因数对应的集合个数
如果 i ( r e s ) i(res) ires没有和 j j j相同的质因数,那么就进行状态转移,让 d p [ j ∣ r e s ] + = d p [ j ] ; dp[j|res]+=dp[j]; dp[jres]+=dp[j];

code
#include <bits/stdc++.h>
using namespace std;
long long a,b,dp[1<<20],p[20]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71},ans=0;
int main() 
{
    cin>>a>>b;
    dp[0]=1;
    for(long long i=a;i<=b;i++) 
	{
        int res=0;
        for(int j=0;j<20;j++)
            if(i%p[j]==0) 
				res|=1<<j;
        for(int j=0;j<1<<20;j++) 
            if(!(res&j))
                dp[j|res]+=dp[j];
    }
    for(int k=0;k<1<<20;k++) ans+=dp[k];
    cout<<ans;
    return 0;
}

总结

代码量都很小,前五道其实都可做,但只A了三道,有点太菜了
1.有些代码还是要敢于去实现(尽管是暴力)
2.好好读题

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值