A - +3 +5 +7
思路:首先我们可以发现这个问题的关键是三个数之间的差,那么对于+3+5+7这个操作可以等价于-2+0+2这个操作,这样便于解题。那么这样的话其实三个数的和是没有变化的,那么要使三个数最后相等那么三个数的和必然是3的倍数。其次-2+0+2这个操作并没有改变三个数的奇偶性,所以所给三个数的奇偶性要是相同的。
然后我们考虑如何得到答案,在以上的条件限制下是必定有解的那么每次操作-2+0+2就会使|x1-ave|+|x2-ave|+|x3-ave|(ave=(x1+x2+x3)/3)减少4,那么最终的答案就是(|x1-ave|+|x2-ave|+|x3-ave|)/4。
#include <bits/stdc++.h>
#define ll long long
#define db double
#define pii pair<int,int>
#define de cout<<"---"<<endl;
#define mem(x,v) memset(x,v,sizeof(x))
#define L(x) x&(-x)
#define pb push_back//emplace_back//priority_queue <int,vector<int>,greater<int> > q;
#define INF 0x3f3f3f3f
#define endl '\n'
//function<void(int)> dfs = [&](int u);
//#define x first
//#define y second
using namespace std;
const int mod=998244353;
int n;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
ll a[3];
void solve(){
for(int i=0;i<3;i++)cin>>a[i];
if((a[0]+a[1]+a[2])%3){
cout<<"-1";
}
else if((a[0]&1)==(a[1]&1)&&(a[0]&1)==(a[2]&1)){
ll ave=(a[0]+a[1]+a[2])/3;
ll res=0;
for(int i=0;i<3;i++){
if(a[i]<ave)res+=ave-a[i];
else res-=ave-a[i];
}
cout<<res/4;
}
else cout<<"-1";
cout<<endl;
return ;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
int TT=1;
cin>>TT;
while(TT--){
solve();
}
return 0;
}
B - Sum-Product Ratio
思路:对于这个问题我们先假设xi和xj已经被选,这样a=xi+xj和b=xi*xj为定值,那么我们发现(xi+xj+xk)/(xi*xj*xk)=(a+xk)(b*xk)=a/b*(1/xk)+1/b,会发现当1/xk取最小值或者最大值时该式子取最大或最小值。那么我们推广到三个数这三个数一定是最大和最小中的三个数,所以按1/x将数组排序,取最小的三个和最大的三个中的三个数构成(xi+xj+xk)/(xi*xj*xk),那么答案必定在这其中。
#include <bits/stdc++.h>
#define ll long long
#define db double
#define pii pair<int,int>
#define de cout<<"---"<<endl;
#define mem(x,v) memset(x,v,sizeof(x))
#define L(x) x&(-x)
#define pb push_back//emplace_back//priority_queue <int,vector<int>,greater<int> > q;
#define INF 0x3f3f3f3f
#define endl '\n'
//function<void(int)> dfs = [&](int u);
//#define x first
//#define y second
using namespace std;
const int mod=998244353;
int n;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
void solve(){
cout<<fixed<<setprecision(15);
cin>>n;
vector<int>a(n);
for(int i=0;i<n;i++)cin>>a[i];
vector<int>b;
sort(a.begin(),a.end(),[&](int x,int y){
double xx=1.0/x,yy=1.0/y;
return xx<yy;
});
for(int i=0;i<3;i++){
b.pb(a[i]);
}
for(int i=max(3,n-3);i<n;i++){
b.pb(a[i]);
}
double mi=1e9,ma=-1e9;
for(int i=0;i<b.size();i++){
for(int j=i+1;j<b.size();j++){
for(int k=j+1;k<b.size();k++){
mi=min(mi,1.0*(b[i]+b[j]+b[k])/b[i]/b[j]/b[k]);
ma=max(ma,1.0*(b[i]+b[j]+b[k])/b[i]/b[j]/b[k]);
}
}
}
cout<<mi<<endl;
cout<<ma<<endl;
return ;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
int TT=1;
while(TT--){
solve();
}
return 0;
}
C - All Pair Digit Sums
思路:首先对于f(a+b),如果a+b中没有发生进位那么显然f(a+b)=f(a)+f(b)。如果发生了进位的话其实对于f(a+b)来说就是有10进位变成1,那么答案将减小9,那么如果发生k次进位,那么f(a+b)=f(a)+f(b)-k*9。所以我们考虑计算出所有ai+aj产生的进位次数t,再用所有f(xi)+f(xj)的和减去9*t即可。
如何考虑计算进位次数呢,我们可以从每一位上来考虑,对于第x低位来说,如果两个数模上10的x+1次方相加超过10的x+1次方那么就是产生了一次进位。那么我们可以根据数模上10的x+1的次方排序,然后用二分的方法找到每一个数有多少个数加起来使其大于10的x+1次方,然后将这个操作在15位上都做一次,就能得到答案了。
#include <bits/stdc++.h>
#define ll long long
#define db double
#define pii pair<int,int>
#define de cout<<"---"<<endl;
#define mem(x,v) memset(x,v,sizeof(x))
#define L(x) x&(-x)
#define pb push_back//emplace_back//priority_queue <int,vector<int>,greater<int> > q;
#define INF 0x3f3f3f3f
#define endl '\n'
//function<void(int)> dfs = [&](int u);
//#define x first
//#define y second
using namespace std;
const int mod=998244353;
int n;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
void solve(){
cin>>n;
vector<ll>a(n);
ll res=0;
for(int i=0;i<n;i++){
cin>>a[i];
for(ll j=10;j<=1000000000000000;j*=10){
res+=a[i]%j/(j/10)*2*n;
}
}
for(ll i=0,j=10;i<15;i++,j*=10){
sort(a.begin(),a.end(),[&](ll x,ll y){
return x%j<y%j;
});
for(int k=0;k<n;k++){
int l=0,r=n;
while(l<r){
int mid=(l+r)/2;
if(a[mid]%j<j-a[k]%j){
l=mid+1;
}
else{
r=mid;
}
}
int t=n-l;
res-=t*9;
}
}
cout<<res<<endl;
return ;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
int TT=1;
while(TT--){
solve();
}
return 0;
}
O(N*15)做法:基数排序+双指针
#include <bits/stdc++.h>
#define ll long long
#define db double
#define pii pair<int,int>
#define de cout<<"---"<<endl;
#define mem(x,v) memset(x,v,sizeof(x))
#define L(x) x&(-x)
#define pb push_back//emplace_back//priority_queue <int,vector<int>,greater<int> > q;
#define INF 0x3f3f3f3f
#define endl '\n'
//function<void(int)> dfs = [&](int u);
//#define x first
//#define y second
using namespace std;
const int mod=998244353;
int n;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
void solve(){
cin>>n;
vector<ll>a(n);
ll res=0;
for(int i=0;i<n;i++){
cin>>a[i];
for(ll j=10;j<=1000000000000000;j*=10){
res+=a[i]%j/(j/10)*2*n;
}
}
vector<ll>b(n);
for(ll i=0,j=10;i<15;i++,j*=10){
vector<ll>c[10];
for(int k=0;k<n;k++){
c[a[k]%j/(j/10)].pb(a[k]);
}
int t=0;
for(int k=0;k<10;k++){
for(auto kk:c[k]){
b[t++]=kk;
}
}
a=b;
int kk=n-1;
for(int k=0;k<n;k++){
while(kk>=0&&a[kk]%j+a[k]%j>=j){
kk--;
}
int t=n-kk-1;
res-=t*9;
}
}
cout<<res<<endl;
return ;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
int TT=1;
while(TT--){
solve();
}
return 0;
}