Panasonic Programming Contest (AtCoder Beginner Contest 195) 题解


Panasonic Programming Contest (AtCoder Beginner Contest 195)

A - Health M Death

判断倍数。

#include <cstdio>
int main() {
	int M, H;
	scanf( "%d %d", &M, &H );
	if( H % M == 0 ) printf( "Yes\n" );
	else printf( "No\n" );
	return 0;
}

B - Many Oranges

橘子重量可以不是整数

  • 最少个

    尽量每个橘子都是最大重量

    此外剩下一点重量,就再弄一个橘子,然后均分重量

  • 最多个

    尽量每个橘子都是最小重量

    此外剩下一点重量,直接均分到每个橘子上

#include <cstdio>
#include <cmath>
using namespace std;
int A, B, n;

int main() {
	scanf( "%d %d %d", &A, &B, &n );
	n *= 1000;
	int min_tot = n / A, max_tot = n / B;
	int min_R = n - min_tot * A, max_R = n - max_tot * B;
	int t;
	t = int( ceil( ( A - min_R ) * 1.0 / min_tot ) );
	if( min_R && t + A > B ) return ! printf( "UNSATISFIABLE\n" );
	t = int( ceil( ( A - max_R ) * 1.0 / max_tot ) ) ;
	if( max_R && B - t < A ) return ! printf( "UNSATISFIABLE\n" );
	printf( "%d %d\n", max_tot + ( max_R ? 1 : 0 ), min_tot );
	return 0;
}

C - Comma

直接 1 e 3 , 1 e 6 , 1 e 9 , 1 e 12 , 1 e 15 1e3,1e6,1e9,1e12,1e15 1e3,1e6,1e9,1e12,1e15做分界线求

#include <cstdio>
#define ll long long

int main() {
	ll n;
	ll x1 = 1e3, x2 = 1e6, x3 = 1e9, x4 = 1e12, x5 = 1e15;
	scanf( "%lld", &n );
	if( n < x1 ) return ! printf( "0" );
	else if( n < x2) return ! printf( "%lld", n - x1 + 1 );
	else if( n < x3 ) return ! printf( "%lld", x2 - x1 + ( n - x2 + 1 ) * 2ll );
	else if( n < x4 ) return ! printf( "%lld", ( x3 - x2 ) * 2ll + x2 - x1 + ( n - x3 + 1 ) * 3ll );
	else if( n < x5 ) return ! printf( "%lld", ( x4 - x3 ) * 3ll + ( x3 - x2 ) * 2ll + x2 - x1 + ( n - x4 + 1 ) * 4ll );
	else return ! printf( "%lld", ( x5 - x4 ) * 4ll + ( x4 - x3 ) * 3ll + ( x3 - x2 ) * 2ll + x2 - x1 + ( n - x5 + 1 ) * 5ll );
	return 0;
}

D - Shipping Center

每个包只能装一袋垃圾

贪心,先装价值最大的垃圾,用最小的能用空间

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 55
struct node {
	int w, v;
}bag[maxn], box[maxn];
int n, m, Q;
int x[maxn];
bool vis[maxn];

bool cmp1( node x, node  y ) {
	return x.v > y.v;
}

bool cmp2( 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", &bag[i].w, &bag[i].v );
	for( int i = 1;i <= m;i ++ )
		scanf( "%d", &box[i].v ), box[i].w = i;
	sort( bag + 1, bag + n + 1, cmp1 );
	sort( box + 1, box + m + 1, cmp2 );
	while( Q -- ) {
		int l, r;
		scanf( "%d %d", &l, &r );
		int ans = 0;
		for( int i = l;i <= r;i ++ ) vis[i] = 1;
		for( int i = 1;i <= n;i ++ )
			for( int j = 1;j <= m;j ++ )
				if( vis[box[j].w] || box[j].v < bag[i].w ) continue;
				else {
					vis[box[j].w] = 1;
					ans += bag[i].v;
					break;
				}
		for( int i = 1;i <= m;i ++ ) vis[i] = 0;
		printf( "%d\n", ans );
	}
	return 0;
}

E - Lucky 7 Battle

倒着推, d p [ n ] = { 0 } dp[n]=\{0\} dp[n]={0},如果最终 0 ∈ d p 0 0∈dp_0 0dp0就胜利

如果上一次操作是 T T T,有一种情况可以达到,那么该余数就可以

d p i = { r   ∣   r ∗ 10 % 7 ∈ d p i + 1   ⋃   ( r ∗ 10 + s i + 1 ) % 7 ∈ d p i + 1 } dp_i=\{r\ |\ r*10\%7∈dp_{i+1}\ \bigcup\ (r*10+s_{i+1})\%7∈dp_{i+1}\} dpi={r  r10%7dpi+1  (r10+si+1)%7dpi+1}

如果上一次操作是 A A A,必须所有情况都达到,该余数才可以

d p i = { r   ∣   r ∗ 10 % 7 ∈ d p i + 1   ⋂   ( r ∗ 10 + s i + 1 ) % 7 ∈ d p i + 1 } dp_i=\{r\ |\ r*10\%7∈dp_{i+1}\ \bigcap\ (r*10+s_{i+1})\%7∈dp_{i+1}\} dpi={r  r10%7dpi+1  (r10+si+1)%7dpi+1}

#include <cstdio>
#include <iostream>
using namespace std;
#define maxn 200005
int n;
char s[maxn], x[maxn];
int dp[maxn][7];

int main() {
	scanf( "%d %s %s", &n, s + 1, x + 1 );
	dp[n][0] = 1;
	for( int i = n - 1;~ i;i -- )
	for( int r = 0;r < 7;r ++ )
		if( x[i + 1] == 'T' )
			dp[i][r] = dp[i + 1][r * 10 % 7] | dp[i + 1][( r * 10 + ( s[i + 1] ^ 48 ) ) % 7];
		else
			dp[i][r] = dp[i + 1][r * 10 % 7] & dp[i + 1][( r * 10 + ( s[i + 1] ^ 48 ) ) % 7];
	if( dp[0][0] ) printf( "Takahashi\n" );
	else printf( "Aoki\n" );
	return 0;
}

F - Coprime Present

差值只有 72 72 72,所以 ∀ x > 72 , x \forall_{x>72},x x>72,x的倍数最多只能出现一次,本质是构成其的质数最多只能出现一次

72 72 72内的质数恰好 20 20 20个,两两互质,就相当于各个质数只出现一次

用状压 D P DP DP完事

#include <cstdio>
#define int long long
#define maxn 1050000
int prime[20] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71 };
int dp[maxn];
int A, B;

signed main() {
	scanf( "%lld %lld", &A, &B );
	dp[0] = 1;
	for( int i = A;i <= B;i ++ ) {
		int t = 0;
		for( int j = 0;j < 20;j ++ )
			if( i % prime[j] == 0 )
				t |= ( 1 << j );
		for( int s = 0;s < ( 1 << 20 );s ++ )
			if( ! ( s & t ) ) dp[s | t] += dp[s];
	}
	int ans = 0;
	for( int i = 0;i < ( 1 << 20 );i ++ )
		ans += dp[i];
	printf( "%lld\n", ans );
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AtCoder Beginner Contest 134 是一场 AtCoder 的入门级比赛,以下是每道题的简要题解: A - Dodecagon 题目描述:已知一个正十二边形的边长,求它的面积。 解题思路:正十二边形的内角为 $150^\circ$,因此可以将正十二边形拆分为 12 个等腰三角形,通过三角形面积公式计算面积即可。 B - Golden Apple 题目描述:有 $N$ 个苹果和 $D$ 个盘子,每个盘子最多可以装下 $2D+1$ 个苹果,求最少需要多少个盘子才能装下所有的苹果。 解题思路:每个盘子最多可以装下 $2D+1$ 个苹果,因此可以将苹果平均分配到每个盘子中,可以得到最少需要 $\lceil \frac{N}{2D+1} \rceil$ 个盘子。 C - Exception Handling 题目描述:给定一个长度为 $N$ 的整数序列 $a$,求除了第 $i$ 个数以外的最大值。 解题思路:可以使用两个变量 $m_1$ 和 $m_2$ 分别记录最大值和次大值。遍历整个序列,当当前数不是第 $i$ 个数时,更新最大值和次大值。因此,最后的结果应该是 $m_1$ 或 $m_2$ 中较小的一个。 D - Preparing Boxes 题目描述:有 $N$ 个盒子和 $M$ 个物品,第 $i$ 个盒子可以放入 $a_i$ 个物品,每个物品只能放在一个盒子中。现在需要将所有的物品放入盒子中,每次操作可以将一个盒子内的物品全部取出并分配到其他盒子中,求最少需要多少次操作才能完成任务。 解题思路:首先可以计算出所有盒子中物品的总数 $S$,然后判断是否存在一个盒子的物品数量大于 $\lceil \frac{S}{2} \rceil$,如果存在,则无法完成任务。否则,可以用贪心的思想,每次从物品数量最多的盒子中取出一个物品,放入物品数量最少的盒子中。因为每次操作都会使得物品数量最多的盒子的物品数量减少,而物品数量最少的盒子的物品数量不变或增加,因此这种贪心策略可以保证最少需要的操作次数最小。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值