我还以为打了这个比赛我的名字会变色。。。。。。
比赛链
1.T206821 [✗✓OI R1] 铝锤制作
题目描述
构造一个正整数数列 a,使 a 中所有元素之积为 n,所有元素之和为 k。如果不存在这样的数列,输出 -1。
输入格式
一行两个正整数 n,k
输出格式
第一行一个整数 m,代表这个数列的长度。
接下来一行 m 个正整数 ai,代表这个数列。要求 1≤m≤1000,1≤ai≤10001。
特别的,如果没有符合要求的数列,直接输出 -1。
本题采用 Special Judge。如果有多种答案,输出任意一种即可。
====================================
做法挺无赖的,找出 n的因数之和最小的情况,小于k就添1做因数,直到添够k
n的因数之和最小的情况都还比k大的话就显然没戏了
#include<bits/stdc++.h>
#define go(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
vector<int>ans;
int main(){
int n,k;
cin>>n>>k;
int nx=n,kx=0;
for(int i=2;i<=n;++i){
while(nx&&nx%i==0){
kx+=i;
if(kx>k){
cout<<"-1";
return 0;
}
nx/=i;
ans.push_back(i);
}
if(nx<=1){
break;
}
}
int dk=k-kx;
int anslen=ans.size()+dk;
cout<<anslen<<endl;
++dk;
while(--dk)
cout<<"1 ";
for(auto t:ans)
cout<<t<<" ";
return 0;
}
2.T204284 [✗✓OI R1] 前方之风
题目描述
给出一个长度为 n 的序列 a 和 q 个询问,第 iii 个询问给出 ki。对于每次询问,你需要进行以下操作:
求出剩下的数的平均数 avg。
将剩下的数中 avg−ki 的数删去。
重复以上两个步骤直到所有数都不会被删去。
输出最后会剩下几个数。
注意:询问之间是独立的,也就是说,不会真的删去那些数。
输入格式
本题有多组测试数据。
第一行一个整数 TTT,表示测试数据的数量。
对于每一组数据,第一行两个整数 n,q表示数字个数和询问数量。
接下来一行 nnn 个整数,第 iii 个整数表示 ai。
接下来一行 qqq 个整数,第 iii 个整数表示 ki。
输出格式
输出共 TTT 行,每行输出 qqq 个整数,第 iii 个数表示第 iii 次询问最终会剩下几个数。
======================================
我的做法是暴力模拟,然后用 前缀和、二分优化 一部分
int h0=lower_bound(a+h,a+n+1,avgll-k)-a;
注意这里减的是a
#include<bits/stdc++.h>
#define go(i,a,b) for(int i=a;i<=b;++i)
#define ll long long
using namespace std;
ll a[100000+10];
ll sum[100000+10];
ll avgsolve(int h,int n){
ll avgll=(sum[n]-sum[h-1])/(n-h+1);
if((sum[n]-sum[h-1])%(n-h+1))
++avgll;
return avgll;
}
void solve(){
int n,q;
scanf("%d%d",&n,&q);
go(i,1,n){scanf("%lld",&a[i]);}
sort(a+1,a+n+1);
//go(i,1,n){printf("%lld=",a[i]);}
//printf("\n");
go(i,1,n){sum[i]=sum[i-1]+a[i];}
ll k;
go(i,1,q){
scanf("%lld",&k);
int h=1;
while(h<=n){
ll avgll=avgsolve(h,n);
int h0=lower_bound(a+h,a+n+1,avgll-k)-a;
if(h0==h)
break;
h=h0;
}
printf("%d ",n-h+1);
}
printf("\n");
}
int main(){
int t=1;
cin>>t;
++t;
while(--t){
solve();
}
return 0;
}