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; }