Codeforces Round #523 (Div. 2) A B C

A. Coins
题解:签到

代码

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

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
#endif
	LL n,s, ans = 0;
	cin>>n>>s;
	ans = s / n;
	if(s % n == 0) {
		cout<< ans <<endl;
	}else {
		cout<< ans + 1 << endl;
	}
    return 0;
}

B. Views Matter

题解:很容易发现,为了保持俯视图不变,每列最少要留一个,为了保持侧视图不变,从 1 1 1 m a x H maxH maxH每行最小要留一个。那么我们就排个序,贪心的去构造,如果当前 a [ i ] &gt; = l a s t a[i] &gt;= last a[i]>=last,那么本次就可以放到 l a s t + 1 last+1 last+1的高度,否则随便放一个位置即可。

#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
int a[100100];
int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
#endif
	int n,m,x,max1 = 0,cnt = 0;
	LL sum = 0;
	cin>>n>>m;
	for(int i = 0; i < n; ++i) {
		scanf("%d",&x);
		max1 = max(max1,x);
		sum += x - 1;
		a[i] = x;
	}
	sort(a,a+n);
	int last = 0;
	for(int i = 0; i < n; ++i) {
		if(i == n - 1 && a[i] > last) {
			last = a[i] - last;
			sum = sum - last + 1;
			break;
		}else if(i == n -1){
			break;
		}
		if(a[i] > last) last++;
	}
	cout<<sum<<endl;
    return 0;
}

C. Multiplicity

题解:首先肯定可以想到 d p [ i ] [ j ] dp[i][j] dp[i][j]表示从 a 1 , a 2 , a 3 , . . . a i a_1,a_2,a_3,...a_i a1,a2,a3,...ai中选取长度为 j j j的好子序列的方案数。那么就有
d p [ i ] [ j ] = { d p [ i − 1 ] [ j ] + d p [ i − 1 ] [ j − 1 ] i f ( a [ i ] % j = = 0 ) d p [ i − 1 ] [ j ] e l s e dp[i][j] = \begin{cases}dp[i-1][j] + dp[i - 1][j-1]&amp;\text{$if(a[i] \% j == 0)$}\\\\ dp[i -1][j]&amp;\text{$else$}\end{cases} dp[i][j]=dp[i1][j]+dp[i1][j1]dp[i1][j]if(a[i]%j==0)else
但是发现时间复杂度是不允许的,所以我们再看会发现 d p [ i ] [ j ] dp[i][j] dp[i][j]只会从两个变量 d p [ i − 1 ] [ j ] dp[i-1][j] dp[i1][j] d p [ i − 1 ] [ j − 1 ] dp[i-1][j-1] dp[i1][j1]转移过来,并且dp[j]只会当 a [ i ] % j = = 0 a[i] \% j == 0 a[i]%j==0时才会被更新。因此就可以只保留一维即可。然后可以在 x \sqrt{x} x 的时间内找出 a [ i ] a[i] a[i]的因子。

代码

#include<bits/stdc++.h>

using namespace std;
const int N = 100100, mod = 1e9+7;
int a[N], dp[N];
int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
#endif
	int n;
	cin>>n;
	for(int i = 1; i <= n; ++i) {
		scanf("%d",&a[i]);
	}
	for(int i = n; i >= 1; --i) {
		for(int j = 1; j * j <= a[i]; ++j) {
			if(a[i] % j == 0) {
				if(j <= n)
					dp[j] = dp[j + 1] + dp[j] + 1, dp[j] %= mod;
				if(j * j != a[i] && a[i] / j <= n) 
					dp[a[i] / j] = dp[a[i] / j] + dp[a[i] / j + 1] + 1, dp[a[i] / j] %= mod;
			}
		}
	}
	printf("%d\n",dp[1]);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值