A.Image Scaling
题意:
给你一个有’.'或者’X’的矩阵。
把X矩阵等比例缩小到最小。
题解:
找到X矩阵的宽w和高h,计算gcd(w,h)。宽和高除gcd就行了。
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N =2e5+6;
//int a[N];
string s[N];
void solve()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>s[i];
int a=0,b=0;
for(int i=1;i<=n;i++){
int t=0;
s[i]=' '+s[i];
for(int j=1;j<=m;j++){
if(s[i][j]=='x')t++;
}
a=max(a,t);
}
for(int j=1;j<=m;j++){
int t=0;
for(int i=1;i<=n;i++){
if(s[i][j]=='x')t++;
}
b=max(b,t);
}
int x=__gcd(a,b);
for(int i=1;i<=b/x;i++){
for(int j=1;j<=a/x;j++){
cout<<'x';
}
cout<<'\n';
}
}
signed main()
{
int T=1;
// cin>>T;
while(T--){
solve();
}
return 0;
}
K.Kill The Monsters
题意:
给定一个k。
有n个怪兽,第
i
i
i个怪兽有自己防御值
a
i
a_i
ai,可以进行以下两种操作。
·所有怪兽防御值-1.
·选一个怪兽,让它的防御值变为
[
a
i
k
]
[\frac{a_i}{k}]
[kai].
问把所有怪兽的防御值都变为<=0的最小操作数。
题解:
首先特判k=1,操作二无意义,只使用操作一。
枚举使用操作二的次数。操作一的次数就是最大值的大小。
优先队列,每次取最大值用一次操作二,然后假设再全部用操作一。取所有答案的最小值。
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N =2e5+6;
int a[N];
//string s[N];
void solve()
{
int n,k;
cin>>n>>k;
priority_queue <int,vector<int>,less<int> > q;
for(int i=1;i<=n;i++){
cin>>a[i];
q.push(a[i]);
}
if(k==1){
int ans=q.top();
cout<<ans<<'\n';
return ;
}
int ans=1e18;
int t=0;
while(!q.empty()){
int x=q.top();
q.pop();
ans=min(ans,t+x);
x/=k;
if(x>0)q.push(x);
t++;
}
ans=min(ans,t);
cout<<ans<<'\n';
}
signed main()
{
int T=1;
// cin>>T;
while(T--){
solve();
}
return 0;
}
I.Interesting Numbers
题意:
给定数字位数n,
1
<
=
n
<
=
60
1<=n<=60
1<=n<=60.n一定是偶数。
给定L,R。
1
0
n
−
1
<
=
L
<
=
R
<
1
0
n
10^{n-1}<=L<=R<10^n
10n−1<=L<=R<10n
问L~R中有多少个数字被为两半,可以得到两个平方数。这两半一定是相同长度。
题解:
一个数有
1
0
30
10^{30}
1030,我们用int128进行运算。
判断一个数有多少个平方数,可以用根号就行.
例如
30
=
5
\sqrt{30}=5
30=5就代表有5个完全平方数。
我们把L,R分为4个数
l
1
,
l
2
,
r
1
,
r
2
l1,l2,r1,r2
l1,l2,r1,r2分别代表L的前后部分,R的前后部分。
设top是与这些数相同位数的最大数,就是9999……
如果
l
1
l1
l1是完全平方数,就加入
t
o
p
−
l
2
−
1
\sqrt{top}-\sqrt{l2-1}
top−l2−1,代表
l
2
l2
l2~top的平方数个数。
如果 r 1 r1 r1是完全平方数,就加入 r 2 \sqrt{r2} r2
再找 l 1 l1 l1~ r 1 r1 r1有多少平方数,乘以 t o p \sqrt{top} top,代表前部分是平方数,后部分是平方数的个数。
代码:
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
typedef __int128 i128;
const __int128 MAX = LONG_LONG_MAX;
inline i128 read() {
i128 x = 0;
char ch = getchar();
while (ch < '0' || ch > '9') {
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = x * 10 + (ch - '0');
ch = getchar();
}
return x;
}
inline void print(i128 x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) {
print(x / 10);
}
putchar(x % 10 + '0');
}
inline i128 Sqrtl(i128 x)
{
i128 l=0,r=MAX,mid;
while(l<r){
mid=(l+r+1)/2;
if(mid*mid>x){
r=mid-1;
}else l=mid;
}
return l;
}
void Solve() {
ll n; cin >> n;
string L, R;
cin >> L >> R;
ll half = n / 2;
string l1_str = L.substr(0, half);
string l2_str = L.substr(half);
string r1_str = R.substr(0, half);
string r2_str = R.substr(half);
i128 l1 = 0, l2 = 0, r1 = 0, r2 = 0, top = 0;
for (char c : l1_str) {
l1 = l1 * 10 + (c - '0');
}
for (char c : l2_str) {
l2 = l2 * 10 + (c - '0');
}
for (char c : r1_str) {
r1 = r1 * 10 + (c - '0');
}
for (char c : r2_str) {
r2 = r2 * 10 + (c - '0');
}
for(ll i = 1; i <= half; i ++ ) {
top = top * 10 + 9;
}
i128 summ = Sqrtl(top) + 1;
i128 sql1 = Sqrtl(l1), sql2 = Sqrtl(l2), sqr1 = Sqrtl(r1), sqr2 = Sqrtl(r2);
i128 ans = 0;
if(r1 == l1) {
if(sqr1 * sqr1 == r1) {
ans = sqr2 - sql2;
if(sql2 * sql2 == l2) ans ++ ;
}
print(ans); return ;
}
if(sqr1 * sqr1 == r1) {
ans += sqr2 + 1;
sqr1 -- ;
}
if(sql1 * sql1 == l1) {
ans += Sqrtl(top) - sql2;
if(sql2 * sql2 == l2) ans ++ ;
}
ans += (sqr1 - sql1) * summ;
print(ans);
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int T = 1;
// cin >> T;
while (T--) {
Solve();
}
// i128 xx=read();
// i128 an=Sqrtl(xx);
// print(an);
return 0;
}
H.Two Convex Polygons
题意:
给定两个凸多边形A,B。
A,B至少有一个共同点的情况下,B可以平移,翻转,反转,问B可以移动的覆盖范围形成的图形的边长是多少。
题解:
B和A至少一个共同点的最大图形,那我们找B图形的最长直径,围绕在A边一圈新构成的图形就是新图形。
求凸包最长直径,用旋转卡壳算法。先求凸包,再求直径,答案就是A的周长加上B直径为半径的圆的周长。
就是模板题
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 3e6 + 5;
const double eps = 1e-8;
const double PI=3.1415926535;
int sgn(double x) {
if (fabs(x) < eps) return 0;
return (x > 0) ? 1 : -1;
}
int n;
struct Point {
double x, y;
Point(double x = 0, double y = 0) : x(x), y(y) {}
void input() { scanf("%lf%lf", &x, &y); }
bool operator<(const Point &b) const {
if (sgn(y - b.y) == 0)
return sgn(x - b.x) < 0;
else
return sgn(y - b.y) < 0;
}
Point operator-(const Point &b) const { return Point(x - b.x, y - b.y); }
double operator^(const Point &b) const { return x * b.y - b.x * y; }
bool operator==(const Point &b) const {
return (sgn(x - b.x)) == 0 && (sgn(y - b.y) == 0);
}
} a[N];
double dis(const Point &a, const Point &b) {
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
struct cmp {
Point p;
cmp() {}
cmp(const Point &p0) { p = p0; }
//以点p为极坐标原点进行极角排序:sort(,,p.cmp(mi));
bool operator()(const Point &a, const Point &b) {
int x = sgn((a - p) ^ (b - p));
if (x == 0)
return sgn(dis(a, p) - dis(b, p)) < 0;
else
return x > 0;
}
};
//向量ab x 向量ac
double cross(Point a, Point b, Point c) { return (b - a) ^ (c - a); }
struct polygon {
int n;
Point p[N];
} convex;
//由a数组求凸包传给 P ———— 没想到求凸包这么简单,之前想得太难了,艹
void getconvex(Point *a, int n, polygon &convex) {
Point mi = a[0];
for (int i = 1; i < n; i++) mi = min(mi, a[i]);
sort(a, a + n, cmp(mi)); //排序:求凸包的准备工作(这里不是极角排序)
int top = 0; // top模拟栈顶
convex.p[top] = a[0];
convex.p[++top] = a[1];
for (int i = 2; i < n; i++) {
while (top > 0 &&
(sgn(cross(convex.p[top - 1], convex.p[top], a[i])) <= 0))
top--;
convex.p[++top] = a[i];
}
convex.n = top + 1;
}
// diameter:直径(zhijing)
double zhijing(Point *a, int n) {
if (n == 2) return dis(a[0], a[1]); //只有两个点
double res = 0;
int r =
1; //今天就栽在了这里。之前一直另的r=0,在Linr(a[0],a[1])的是时候就会出问题emmm
a[n] = a[0];
for (int i = 0; i < n; i++) {
while (sgn(cross(a[i], a[i + 1], a[r + 1]) -
cross(a[i], a[i + 1], a[r])) > 0)
r = (r + 1) % n;
if (sgn(dis(a[i], a[r]) - res) > 0) res = dis(a[i], a[r]);
if (sgn(dis(a[i + 1], a[r]) - res) > 0) res = dis(a[i + 1], a[r]);
//这里为保险起见(一条线对应两个点的时候)。好像不要也是对的,为什么?这是一个大问题
continue;
while (sgn(cross(a[i], a[i + 1],
a[r + 1] - cross(a[i], a[i + 1], a[r]))) == 0) {
r = (r + 1) % n;
if (sgn(dis(a[i], a[r]) - res) > 0) res = dis(a[i], a[r]);
if (sgn(dis(a[i + 1], a[r]) - res) > 0) res = dis(a[i + 1], a[r]);
}
}
return res;
}
void solve()
{
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].x>>a[i].y;
}
double ans=0;
for(int i=2;i<=n;i++){
ans+=dis(a[i],a[i-1]);
}
ans+=dis(a[1],a[n]);
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i].x>>a[i].y;
}
getconvex(a, n, convex);
double cn= zhijing(convex.p, convex.n);
ans+=2*PI*cn;
cout << fixed << setprecision(13) << ans << "\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int T;
cin>>T;
while(T--){
solve();
}
}```