Codeforces Round #643 (Div. 2)
A Sequence with Digits
CF 1355A
按照题目的公式一样取出该数中每一位中的最大和最小相乘再加上该数就得到下一个数了,因为肯定会有最小为0的时候(0乘任何数都为0)所以只要碰到0了后面就一直加的是0也就是不变,注意特例1 1就行了
#include <iostream>
#include <algorithm>
using namespace std;
int main(){
int t;
scanf("%d",&t);
while(t--){
long long num,k;
scanf("%lld%lld",&num,&k);
k--;
long long ans=num;
while(k--){
long long num1=ans;
int mini=10,maxi=0;
while(num1){
int pos=num1%10;
num1/=10;
maxi=max(maxi,pos);
mini=min(mini,pos);
}
if (mini==0)
break;
ans=ans+mini*maxi;
}
printf("%lld\n",ans);
}
return 0;
}
B - Young Explorers
CF 1355B
神坑的一题,结束后被hack掉了一个代码,我也母鸡为什么再TEST26 TLE,后面又重新写了一份,感觉复杂度相差不大呀!!!!!!!
每个人都有一个缺乏经验值,值为ei的人只能加入大于等于e个人的团,求最多能组成多少个团,如果有必要,有些人可以不用组团让他留在营地
排序后遍历算出相同ei值得人有多少个,在此ei值下能组多少个团(直接整除),之后多余得人可以和ei之前组完团多余的人进行组团
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
int ans[200005];
vector<int>v;
int main(){
int t;
scanf("%d",&t);
while(t--){
v.clear();
int n;
scanf("%d",&n);
memset(ans,0,sizeof(ans));
while(n--){
int num;
scanf("%d",&num);
if (!ans[num]) v.push_back(num);
ans[num]++;
}
sort(v.begin(),v.end());
int sum=0;
int sum1=0;
for (int j=0;j<v.size();j++){
int i=v[j];
int pos=ans[i]/i;
int pos1=ans[i]%i;
pos=pos+(sum1+pos1)/i;
sum1=(sum1+pos1)%i;
sum+=pos;
}
printf("%d\n",sum);
}
return 0;
}
通过的代码
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int ans[200005];
int main(){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
for (int i=0;i<n;i++) scanf("%d",ans+i);
sort(ans,ans+n);
int sum=0;
int sum1=0;
for (int i=0;i<n;i++){
int j=i+1;
while(j<n&&ans[j]==ans[i]) j++;
int pos=(j-i)/ans[i];
int pos1=(j-i)%ans[i];
pos=pos+(sum1+pos1)/ans[i];
sum1=(sum1+pos1)%ans[i];
sum+=pos;
if (j>=n) break;
i=j-1;
}
printf("%d\n",sum);
}
return 0;
}
C - Count Triangles
CF 1355C
给定四个数。A,B,C,D,从这四个数组成的三个区间内,每个区间取一个整数当三角形的边,问能组成多少个三角形
推公式,别想着一股脑的模拟就行,因为(A,B)区间内的值确定了为i,假设j在(B,C)内,那么如果能组成三角形就要满足j+i+1要大于C也就是第三条边必要能在(C,D)内取得所以j要满足大于等于C-i+1同时j要大于B,所以j就取max(C+1-i,B),然后第三条边的取值在一个区间内分情况讨论了,之后随着j的增加区间变小所以是一个等差数列求和了。。。。。。后面留给你们慢慢推
#include <iostream>
#include <algorithm>
using namespace std;
int main(){
long long a,b,c,d;
scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
long long sum=0;
for (long long i=a;i<=b;i++){
long long j=c+1-i;
if (j<b) j=b;
if (j+i-1>=d) sum=sum+(d-c+1)*(c-j+1);
else{
if (c-j+1<d-(j+i-1)+1) sum=sum+(((j+i-1)-c+1)*2+c-j)*(c-j+1)/2;
else sum=sum+(((j+i-1)-c+1)*2+d-(j+i-1))*(d-(j+i-1)+1)/2+(c-j-d+(j+i-1))*(d-c+1);
}
}
printf("%lld\n",sum);
return 0;
}
D - Game With Array
CF 1355D
给N和S,叫你确定一个序列和K,使得这N个数的和为S,并且所有子序列中没有任何一个子序列的所有元素之和等于K或者S-K的
用1来构造,前n-1个全为1剩下一个为s-n+1,如果s-n<=n-1那个不好意思,这个序列的子序列可以构造出1-S中的任何数,其他情况下,除此之外的其他情况,永远构造不出s-n
#include <iostream>
#include <algorithm>
using namespace std;
int main(){
int n,s;
scanf("%d%d",&n,&s);
if (n==1&&s==1){
printf("NO\n");
return 0;
}
if (s-n<=n-1) printf("NO\n");
else{
printf("YES\n");
for (int i=0;i<n-1;i++) printf("1 ");
printf("%d\n",s-n+1);
printf("%d\n",s-n);
}
return 0;
}