题目链接:http://arc079.contest.atcoder.jp/
这两道题目正好是完全相反的, 所以放到一起写。
题意就是说给你n个数 (2 <= n <= 50) 每一次从a[i]中取出一个最大的减去n, 其他的n-1个数加上1, 一直重复直到最大的a[i] < n, 执行次数记为k。
D题给你k让你构造数列A, E题是给你N和A数列, 让你求k
解题思路:两道题读完了之后,我感觉E应该好想一些, 因为是正着推, 我就模拟了一下他的要求。 但是复杂度不太会算, 觉着这个/ 应该比log还要小或者就是log左右, 不知道想的对不对。 交上去就A了, 跑了 2ms。
之后就开始想D题,刚开始思路完全跑偏, 最后同学讲的规律。
比如说
5
5 5 5 5 5 这个, 变成合法的次数为5
5
6 6 6 6 6 变成合法次数为10
所以我们可以构造一个最终状态n为50 , 每一a[i] 都为49的数列。 逆向模拟, a[i] += k / n
最后会有k % n个, 就需要单独模拟一下。
E题:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;
const int MaxN = 50;
LL a[MaxN + 5];
LL cnt[MaxN + 5];
int n;
int main(){
while(~scanf("%d", &n)){
for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
LL tot = 0, ans = 0;
bool flag = true;
while(flag){
flag = false;
tot = 0;
for(int i = 1; i <= n; i++){
cnt[i] = a[i] / n;
a[i] = a[i] % n;
tot += cnt[i];
}
ans += tot;
for(int i= 1; i <= n; i++){
a[i] += tot - cnt[i];
if(a[i] >= n) flag = true;
}
}
printf("%lld\n", ans);
}
return 0;
}
D题:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
using namespace std;
typedef long long LL;
const int MaxN = 50;
const LL INF = 5e17;
LL a[MaxN + 5], cnt[MaxN + 5];
LL k;
int main(){
while(~scanf("%lld", &k)){
int n = 50;
LL temp = k / n;
for(int i = 1; i <= n; i++) a[i] = n - 1;
for(int i = 1; i <= n; i++) a[i] += temp;
for(int i = 1; i <= k % n; i++){
a[i] += n;
for(int j = 1; j <= n; j++){
if(i == j) continue;
a[j]--;
}
}
printf("50\n");
for(int i = 1; i <= n; i++) printf("%lld ", a[i]);
}
return 0;
}