Comet OJ

A 双十一特惠 (简单版)

 n  <=  1e19,   1e9 > 1(8)

https://www.cometoj.com/contest/79/problem/A?problem_id=4198

#include<bits/stdc++.h>

using namespace std;

int main(){
    int t; cin >> t; 
    while(t--) {
        int cnt1 = 0; 
        int n;cin >> n;
        int pr[] = {1,11,111,1111,11111,111111,1111111,11111111,111111111};
        for(int i = 8; i >= 0; i--) {
            cnt1 += n/pr[i];
            n %= pr[i];
        }
        if(cnt1 > 9) cout << "Impossible
";
        else cout << cnt1 << endl;
    }
    return 0;
}

D 困难版

https://www.cometoj.com/contest/79/analysis // dm聚聚在线讲题, 走过路过不要错过

https://atcoder.jp/contests/agc011/tasks/agc011_e    //类似的题目,AtCoder Grand 011E Increasing Numbers

 可以假设一个 特殊的进制, 1 11 111 1111 …………

 然后将十进制数转为这个进制, 比如说 234 -> 2,1,1(2*111+1*11+1) 

 该进制下的位数相加为所需要的 “好的数” 的数量,  我们会发现当除了最后一位其他位数 大于9时, 可以转化为更小的该进制
 比如说    11,0,0 ->  1,0,10,0   10,0,1,0 ->1,0,0,0,10  
 然后我们可以将第i个进制为i , 取该进制下的贡献

 11,0,0 ->  1,0,10,0(11*3=33   1*4+10*1=14)   10,0,1,0 ->1,0,0,0,10 (10*4+2=42   1*5+10=15) 
 会发现当有位数大于9时(非末位)转化为更小的进制 贡献更小, 所以我们可以一直将他转化为更小的  故符合贪心选择性质
 结论: 将一个十进制数用“好的数”表示时, 尽可能用当前满足的最大的“好的数”表示,  所耗费的“好的数”数量最少

 题解: 将 u = v*9 ,用尽量少的10i -1 数来表示u, 需要尽量少的 1 可以让 u 表示为 若干个10的幂次方之和,

 u+x =  10a1+10a2+10a3+……+10ax, 所以u+x的各位数之和<= x, x<=1e7 所以可以直接暴力枚举x

 (  更详细的证明 可以参照这个博客 https://blog.csdn.net/Orzage/article/details/85015246)  O(n)  --位数

#include <algorithm>
#include <iostream>
#include <string>
#include <cmath>
#define _for(i,a,b) for(int i = (a); i < (b); i++)
#define _rep(i,a,b) for(int i = (a); i <= (b); i++)
#define _per(i,a,b) for(int i = (a); i > (b); i--)
void solve(){
    std::string s; std::cin >> s;
    int n = s.size(), sum = 0;
    std::vector<int> v(n+2, 0);
    _rep(i,1,n) v[i] = (s[i-1]-'0')*9;
    _per(i,n-1,0) v[i-1] += v[i]/10, v[i] %= 10;
    _rep(i,0,n) sum += v[i];
    _rep(p,1,1e6){
        int i = n;
        while(v[i] >= 9) v[i--] -= 9, sum -= 9;
        sum++, v[i]++;
        if(p >= sum && p%9 == sum%9) {
            std::cout << p << '
';
            return;
        }
    }
}

int main(){
    int t; std::cin >> t;
    while(t--) solve();
    return 0;
}

B 当我们同心在一起 

https://www.cometoj.com/contest/79/problem/B?problem_id=4199

#include<bits/stdc++.h>
#define ll long long
//暴力枚举每个坐标作为圆心的情况下 能有几个距离圆心距离相等的点,ans += f[cnt1]
//将每个点作为圆心 其他点到圆心的距离作为数组 sort 再求有几个, 浮点数精度会有误差 所以把距离函数改成 ll 不取平方根就可以ac
//也可以将每次得到的距离用 map存, O(t*n2
using namespace std; ll dist(ll x1, ll y1, ll x2, ll y2){ return ((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); } int main(){ int t; t = 1; //cin >> t; while(t--) { int n;cin >> n; int ans = 0; //vector<pair<int, int> > dot(n+1); ll dx[2020], dy[2020]; for(int i = 0; i < n; i++) cin >> dx[i] >> dy[i]; for(int i = 0; i < n; i++) { int x = i; vector<ll> dis; for(int j = 0; j < n; j++){ if(i == j) continue; ll distan = dist(dx[i], dy[i], dx[j], dy[j]); dis.push_back(distan); //cout << "i = " << i << " dis = " << distan << endl << endl; } sort(dis.begin(), dis.end()); ll y = -1; int cnt1 = 1; for(int j = 0; j < n-1; j++){ //cout << dis[j] << " y = " << y << " cnt1 = " << cnt1 << endl << endl; if(dis[j] == y) cnt1++; else { ans += (cnt1*(cnt1-1)*(cnt1-2)/6); y = dis[j]; cnt1 = 1; } } //cout << "ans = " << ans << " cnt1= "<< cnt1<< " f[cnt1]" << f[cnt1] << endl << endl; ans += (cnt1*(cnt1-1)*(cnt1-2)/6); //cout << "!111 "; } cout << ans << endl; } return 0; }
#include<bits/stdc++.h>
#define ll long long
//看了题解, 稍微优化了下
using namespace std;
ll dist(ll x1, ll y1, ll x2, ll y2){return ((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}
int main(){
    int t; 
    t = 1;
    while(t--) {
        int n;cin >> n;
        int ans = 0;
        //vector<pair<int, int> > dot(n+1);
        ll dx[2020], dy[2020];
        for(int i = 0; i < n; i++) cin >> dx[i] >> dy[i];
        for(int i = 0; i < n; i++) {
            vector<ll> dis;
            for(int j = 0; j < n; j++){
                dis.push_back(dist(dx[i], dy[i], dx[j], dy[j]));
            }
            sort(dis.begin(), dis.end());
            for(int j = 0, k; j < n; j = k){
                for(k = j; dis[k] == dis[j]; k++);
                ans += (k-j)*(k-j-1)*(k-j-2)/6;
            }
        }
        cout << ans << endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/163467wyj/p/11939346.html