上午打了一场cf题目难度好难...1个半小时才过了AB...
A:Problem - A - Codeforces (Unofficial mirror by Menci)
一开始看了10分钟没看懂题意,后面才看懂了。
可以暴力枚举,因为假如r-l>100,那么r和l之间的数字一定有90或09,只要ans=9就break即可,
但需要注意5 5和11 11等情况,我就是没考虑,然后wa了两发..
时间复杂度为O(T*6*100)不会超时
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
int t;
int l,r;
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%d",&l,&r);
int num=0;
int ans=0;
// if(l<10&&r<10){
/// printf("%d\n",l);
// continue;
// }
for(int i=l;i<=r;i++){
int maxn=0;
int minn=inf;
int now=i;
while(now!=0){
maxn=max(maxn,now%10);
minn=min(minn,now%10);
now=now/10;
}
if(maxn-minn>=ans){//注意可以取代等号比如11, 5,7,
ans=maxn-minn;
num=i;
if(ans==9)break;
}
}
printf("%d\n",num);
}
return 0;
}
B:Problem - B - Codeforces (Unofficial mirror by Menci)
这题题意是真的长,幸好还比较好理解,一开始我没啥思路,觉得暴力枚举肯定会超时(三层循环),后面我没思路了,试了试果然超时,然后我看了看样例,觉得答案为每一行最大值减最小值的两倍然后求总和,然后没看第三个样例就开始做题了,第三个样例的答案为奇数
想了快1个小时吧,想到了前缀和可以做
比如将数组a从大到小排序,比如 4 3 2 1,结果为3*4-(3+2+1)+2*3-(2+1)+2*1-1
二维数组的排序我还不会还搜了搜...sort(a[i].begin(),a[i].end(),greater<ll>() );
写的过程还是比较痛苦的...
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
int t;
int n,m;
vector<ll>a[300005];
vector<ll>b[300005];
//vector<ll>c[300004];
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(int i=0;i<=m;i++)a[i].clear();
for(int i=0;i<=m;i++)b[i].clear();
// for(int i=0;i<=m;i++)c[i].clear();
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
int x;
scanf("%d",&x);
a[j].push_back(x);
}
}
for(int i=0;i<m;i++)sort(a[i].begin(),a[i].end(),greater<ll>() );
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(j==0){
b[i].push_back(a[i][j]);
}else{
b[i].push_back(b[i][j-1]+a[i][j]);
}
}
}
ll ans=0;
for(int i=0;i<m;i++){
for(int j=0;j<n-1;j++){
ans=ans+(n-1-j)*a[i][j]-(b[i][n-1]-b[i][j]);
}
}
printf("%lld\n",ans);
}
return 0;
}
在网上还看到了一种思路:统计每一个数字需要加多少次,需要减多少次
首先先将数组排序,5 4 3 2 1,对于5需要加4次,减0次,对于4需要加3次,减1次
1需要加0次,减4次,所以第i个数组需要加n-i次减i-1次,即加n-2i+1次
继续加油!!