AtCoder | ARC064 | 题解

ARC064

感觉这场还是挺简单的(但这并不影响我仍然不会做QwQ

E E E题感觉啥都想到了。…知道要去求最短路…但却没有想到dij…???(smg

C. Boxes and Candies

肯定是尽量改 [ 2 , n − 1 ] [2,n-1] [2,n1]的嘛…所以你就一遍扫下来就行啦呀

#include 
#define ll long long
using namespace std;
const int N = 1e5 + 10;
ll a[N];

int main() {
	int n, x;
	cin >> n >> x;
	for(int i = 1; i <= n; ++i) {
		scanf("%lld", &a[i]);
	}
	ll pos = 0;
	for(int i = 2; i <= n; ++i) {
		ll gg = max(0ll, (a[i] + a[i - 1]) - x);
		a[i] -= min(a[i], gg);
		pos += gg;
	}
	printf("%lld\n", pos);
	return 0;
}

D.An Ordinary Game

可以发现

  • 如果头和尾是相同的话 假设这么一个串 a b a b a ababa ababa( b b b可以为任意字符)

    那么长度为奇数的话必败

  • 如果头和尾不相同 那么这么一个串 a c a c acac acac( a , c a,c a,c也可以为任意字符)

    那么长度为偶数的话必败

#include 
using namespace std;
const int N = 1e5 + 10;
char lx[N];

int main() {
	scanf("%s", lx + 1);
	int len = strlen(lx + 1);
	if(lx[1] == lx[len]) {
		if(len & 1) printf("Second\n");
		else printf("First\n");
	} else {
		if(len & 1) printf("First\n");
		else printf("Second\n");
	}
	return 0;
}

E.Cosmic Rays

把每一个圆当作一个点 (圆和圆之间的距离是圆心距离-半径和 和 0 0 0取个max就行啦)

然后你跑一遍最短路就行了

#include 
using namespace std;
const int N = 1010;
const double inf = 1e-12;
struct Point {
	double x, y;
} c[N];
int vis[N];
double R[N], f[N];

double pf(double x) {
	return x * x;
}

double dis(Point A, Point B) {
	return sqrt(pf(A.x - B.x) + pf(A.y - B.y));
}

double get(int k, int j) {
	return max(0.0, dis(c[k], c[j]) - (R[k] + R[j]));
}

int main() {
	for(int i = 1; i <= 2; ++i) {
		scanf("%lf%lf", &c[i].x, &c[i].y);
		R[i] = 0;
	}
	int n;
	scanf("%d", &n);
	n += 2;
	for(int i = 1; i <= n; ++i) f[i] = 3e9;
	for(int i = 3; i <= n; ++i) {
		scanf("%lf%lf%lf", &c[i].x, &c[i].y, &R[i]);
	}
	f[1] = 0;
	for(;;) {
		int be = -1;
		for(int i = 1; i <= n; ++i) {
			if(vis[i]) continue;
			if(be == -1 || f[be] > f[i]) be = i;
		}
		if(be == -1) break;
		vis[be] = 1;
		for(int i = 1; i <= n; ++i) {
			f[i] = min(f[i], f[be] + get(i, be));
		}
	}
	printf("%.12f\n", f[2]);
	return 0;
}

F.Rotated Palindromes

我们设 f [ i ] f[i] f[i]表示长度为 i i i且没有长度大于1的循环节的回文串个数

那么显然 f [ i ] = k ⌈ i 2 ⌉ − ∑ d ∣ i f [ d ] f[i]=k^{\lceil{\dfrac{i}{2}}\rceil}-\sum_{d|i}f[d] f[i]=k2idif[d]

由于每次你只需要根号级别复杂度…所以这个可以很快处理出来

那么最后的 a n s = ∑ d ∣ n [ d & 1 ] ∗ d ∗ f [ d ] + [ ! ( d & 1 ) ] ∗ d 2 ∗ f [ d ] ans=\sum_{d|n}[d\&1]*d*f[d]+[!(d\&1)]*\dfrac{d}{2}*f[d] ans=dn[d&1]df[d]+[!(d&1)]2df[d]

因为长度为偶数时 移到一半的时候就会开始重复 所以要除以2

#include 
#define ll long long
using namespace std;
const int mod = 1e9 + 7;
int n, k;
map<int, ll> f;

ll add(ll x, ll y) {
	return (x + y + mod) % mod;
}

void Add(ll &x, ll y) {
	x = (x + y + mod) % mod;
}

ll mul(ll x, ll y) {
	return (x * y) % mod;
}

void Mul(ll &x, ll y) {
	x = (x * y) % mod;
}

ll q_pow(ll x, int y) {
	ll ans = 1;
	for(; y; y >>= 1) {
		if(y & 1) Mul(ans, x);
		Mul(x, x);
	}
	return ans;
}

ll get(int x) {
	if(!f.count(x)) {
		int len = sqrt(x);
		ll pos = q_pow(k, (x / 2) + (x & 1));
		for(int i = 2; i <= len; ++i) {
			if(x % i) continue;
			Add(pos, -get(i));
			if(i * i != x) Add(pos, -get(x / i));
		}
		if(x != 1) Add(pos, -k);
		return f[x] = pos;
	} else return f[x];
}

int main() {
	scanf("%d%d", &n, &k);
	int len = sqrt(n);
	ll ans = 0;
	for(int i = 1; i <= len; ++i) {
		if(n % i) continue;
		if(i & 1) Add(ans, mul(i, get(i)));
		else Add(ans, mul(i / 2, get(i)));
		if(i * i != n) {
			int now = n / i;
			if(now & 1) Add(ans, mul(now, get(now)));
			else Add(ans, mul(now / 2, get(now)));
		}
	}
	printf("%lld\n", (ans + mod) % mod);
	return 0;
}

本文作者:Averyta

博客地址:https://blog.csdn.net/AngryVegetable

你可能感兴趣的:(-----网站-----,AtCoder,ARC)