【A】水题,预处理一下就可以了。
【B】构造,判断一下最大值和最小值的差是否>k,是的话无解,否者xjb构造就行了。
int n, k, a[111];
int main()
{
while(scanf("%d%d",&n,&k)!=EOF)
{
int mx = 0, mi = 200;
for(int i = 1; i <= n; i++){
scanf("%d",&a[i]);
mx = max(mx, a[i]);
mi = min(mi, a[i]);
}
if(mx-mi>k){
puts("NO");
continue;
}
printf("YES\n");
for(int i = 1; i <= n; i++){
int cc = 1;
for(int j = 1; j <= a[i]; j++){
printf("%d ",cc++);
if(cc == k + 1) cc = 1;
}
printf("\n");
}
}
}
【C】不会,看了网上的题解。给了每个数的每一位的数字之和,要你构造原来的这个序列,满足递增的顺序并且满足最后一位最小。贪心的策略是:直接找比前一位大,并且最小的数。
const int maxn = 333;
int a[maxn],res[maxn],len,n;
void print(int t)
{
for(int i = 1; t > 0; i++){
while(res[i] < 9 && t > 0) res[i]++, t--;
len = max(len, i);
}
for(int i = len; i >= 1; i--) printf("%d",res[i]);
printf("\n");
}
void solve(int t)
{
if(t > 0) print(t);
else{
for(int i = 1; i <= len + 1; i++){
if(t > 0){
while(res[i] == 9) res[i] = 0, t += 9, i++;
res[i]++,t--;
if(i == len + 1) len++;
print(t);
break;
}
else
{
t += res[i], res[i] = 0;
}
}
}
}
int main()
{
while(scanf("%d",&n) != EOF)
{
a[0] = 0;
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
len = 1;
for(int i = 1; i <= n; i++){
int t = a[i] - a[i-1];
solve(t);
}
}
}
【E】给了一个字符串,要你求所有字串的一个比例之和,这个比例等于元音字母的个数除以字串长度。很容易想到,把这个串变成01串,维护一个前缀和。枚举字串的长度k,对于每一个k,答案等于Sigma(s[k]-s[0]+(s[k+1]-s[1])+...+(s[n]-s[n-k])),很容易发现维护前缀和之后,分子变成了sum[n]-sum[k-1]-sum[n-k]。然后O(1)的算出这个值。加上枚举长度,复杂度才O(len)。
const int maxn = 5e5+20;
char s[maxn];
int a[maxn];
LL sum[maxn];
int main()
{
while(scanf("%s",s+1)!=EOF)
{
int len = strlen(s+1);
for(int i = 1; i <= len; i++){
if(s[i] == 'I' || s[i] == 'E' || s[i] == 'A' || s[i] == 'O' || s[i] == 'U' || s[i] == 'Y'){
a[i] = 1;
}
else{
a[i] = 0;
}
}
memset(sum, 0, sizeof(sum));
for(int i = 1; i <= len; i++){
a[i] += a[i-1];
sum[i] = sum[i-1] + a[i];
}
double ans = 0.0;
for(int k = 1; k <= len; k++)
{
ans = ans + (double)(sum[len] - sum[k - 1] - sum[len - k]) / k*1.0;
}
printf("%.8f\n", ans);
}
return 0;
}