LightOJ - 1078 Integer Divisibility
思路
博弈
先手必胜: 可以走到必败状态
先手必败: 无论如何也走不到必败状态
该题,模拟一下就知道
- 若Alice先手的情况,则
n%3 == 1
是先手必败状态 - 若Bob先手的情况,则
n%3 == 0
是先手必败状态
代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main() {
int T;
scanf("%d", &T);
int id = 0;
while(T --) {
int n;
string name;
string ans;
cin >> n >> name;
if(name == "Alice") {
if(n % 3 == 1) {
ans = "Bob";
}
else
ans = "Alice";
}
else {
if(n % 3 == 0) {
ans = "Alice";
}
else
ans = "Bob";
}
printf("Case %d: %s\n", ++id, ans.c_str());
}
return 0;
}
LightOJ - 1124 Cricket Ranking
思路
和Dev的鲜花类似
唯一不同的是:
鲜花是可以取【0,A[i]】
这里是[l,r]
偏移一下就可以了
[l, r] -> [0, r-l], 同时N也要减去l
代码
#include<iostream>
#include<cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 20, mod = 100000007;
LL A[N];
LL n, m;
int down;
LL qmi(LL a, LL b, int mod) {
LL res = 1;
while(b) {
if(b & 1)
res = (LL)res * a % mod;
a = (LL)a * a % mod;
b >>= 1;
}
return res;
}
LL C(LL a, LL b) {
if(a < b)
return 0;
int up = 1;
for (int i = a; i > a - b; i --) {
up = (LL)i % mod * up % mod;
}
return (LL)up * down % mod;
}
int main() {
int T;
int id = 0;
scanf("%d", &T);
while(T --) {
scanf("%lld%lld", &n, &m);
for (int i = 0; i < n; i ++){
LL l, r;
scanf("%lld%lld", &l, &r);
r -= l;
m -= l;
A[i] = r;
}
// 预处理1/((n-1)!)
down = 1;
for (int i = 1; i <= n - 1; i ++)
down = (LL)i * down % mod;
down = qmi(down, mod - 2, mod);
LL res = 0;
for (int i = 0; i < 1 << n; i ++) {
int sign = 1;
LL a = m + n - 1, b = n - 1;
for (int j = 0; j < n; j ++)
if(i >> j & 1) {
sign *= -1;
a -= A[j] + 1;
}
res = (res + C(a, b) * sign) % mod;
}
printf("Case %d: %lld\n", ++id, (res + mod) % mod);
}
return 0;
}
LightOJ - 1144 Ray Gun
思路
∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = 1 ] \sum_{i=1}^n \sum_{j=1}^{m}[gcd(i,j)=1] ∑i=1n∑j=1m[gcd(i,j)=1]
莫比乌斯函数,容斥原理, 整除分块
代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1e6 + 10;
int primes[N];
bool st[N];
int cnt;
int mu[N];
int sum[N];
void moblus()
{
memset(st, false, sizeof st);
mu[1] = 1;
cnt = 0;
for (int i = 2; i < N; i ++) {
if(!st[i]) {
primes[cnt++] = i;
mu[i] = -1;
}
for (int j = 0; primes[j] * i < N; j ++){
int t = primes[j] * i;
st[t] = true;
if(i % primes[j] == 0) {
mu[t] = 0;
break;
}
mu[t] = mu[i] * -1;
}
}
for (int i = 1; i < N; i ++) {
sum[i] = sum[i - 1] + mu[i];
}
}
int main() {
moblus();
int T;
scanf("%d", &T);
int id = 0;
while(T --) {
long long n, m;
scanf("%lld%lld", &n, &m);
if(n > m)
swap(n, m);
long long res = 0;
for (long long l = 1, r; l <= n; l = r + 1) {
r = min(n, min(n / (n / l), m / (m / l)));
res += (sum[r] - sum[l - 1]) * (long long)(n / l) * (m / l);
}
if(n)
res++;
if(m)
res ++;
printf("Case %d: %lld\n", ++id, res);
}
return 0;
}