太懶,強迫自己一波。MDZZ
A
題意:有
遊戲規則要求選出來的人圍成一個圓且任意兩個人到圓心的連線夾角必須是
我們把
問題就變成
記
這樣
一開始推出公式
不管了,過了再說。。。但是
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <cstdlib>
#define ll o<<1
#define rr o<<1|1
#define CLR(a, b) memset(a, (b), sizeof(a))
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 2e5 + 10;
const int INF = 1e9 + 10;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int MOD = 1e9 + 7;
void add(LL &x, LL y) { x += y; x %= MOD; }
LL euler(int n) {
LL ans = n;
for(int i = 2; i * i <= n; i++) {
if(n % i == 0) {
ans = ans / i * (i - 1);
while(n % i == 0) n /= i;
}
}
if(n > 1) ans = ans / n * (n - 1);
return ans;
}
struct Matrix {
LL a[2][2];
};
Matrix multi(Matrix x, Matrix y) {
Matrix z; CLR(z.a, 0);
for(int i = 0; i < 2; i++) {
for(int k = 0; k < 2; k++) {
if(x.a[i][k] == 0) continue;
for(int j = 0; j < 2; j++) {
z.a[i][j] = (z.a[i][j] + x.a[i][k] * y.a[k][j] % MOD) % MOD;
}
}
}
return z;
}
Matrix Pow(Matrix x, int n) {
Matrix ans;
for(int i = 0; i < 2; i++) {
for(int j = 0; j < 2; j++) {
if(i == j) {
ans.a[i][j] = 1;
}
else {
ans.a[i][j] = 0;
}
}
}
while(n) {
if(n & 1) {
ans = multi(ans, x);
}
x = multi(x, x);
n >>= 1;
}
return ans;
}
LL Work(int n) {
if(n == 1) return 1;
if(n == 2) return 3;
Matrix x;
x.a[0][0] = 1; x.a[0][1] = 1; x.a[1][0] = 1; x.a[1][1] = 0;
Matrix y = Pow(x, n - 2);
return (1LL * 3 * y.a[0][0] % MOD + 1LL * 1 * y.a[1][0] % MOD) % MOD;
}
LL pow_mod(LL a, int n) {
LL ans = 1;
while(n) {
if(n & 1) {
ans = ans * a % MOD;
}
n >>= 1;
a = a * a % MOD;
}
return ans;
}
int main()
{
// for(int i = 1; i <= 8; i++) {
// cout << Work(i) << endl;
// }
int n;
while(scanf("%d", &n) != EOF) {
if(n == 1) {
printf("2\n");
continue;
}
LL ans = 0;
for(int i = 1; i * i <= n; i++) {
if(n % i == 0) {
add(ans, Work(i) * euler(n / i) % MOD);
if(i * i != n) {
add(ans, Work(n / i) * euler(i) % MOD);
}
}
}
printf("%lld\n", ans * pow_mod(n, MOD - 2) % MOD);
}
return 0;
}
B
題意:求解區間不同
思路:枚舉右端點,二分找到連續區間
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <cstdlib>
#define ll o<<1
#define rr o<<1|1
#define CLR(a, b) memset(a, (b), sizeof(a))
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e5 + 10;
const int INF = 1e9 + 10;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int MOD = 1e9 + 7;
void add(LL &x, LL y) { x += y; x %= MOD; }
int g[MAXN][21], a[MAXN];
map<int, int> lp;
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
void RMQ_init(int N) {
for(int i = 1; i <= N; i++) {
g[i][0] = a[i];
}
for(int j = 1; (1 << j) <= N; j++) {
for(int i = 1; i + (1 << j) - 1 <= N; i++) {
g[i][j] = gcd(g[i][j-1], g[i + (1 << (j-1))][j-1]);
}
}
}
int Query(int L, int R) {
int k = 0;
while((1 << (k + 1)) <= R - L + 1) k++;
return gcd(g[L][k], g[R - (1 << k) + 1][k]);
}
struct Node {
int l, r, id;
};
Node num[MAXN];
bool cmp1(Node a, Node b) {
return a.r < b.r;
}
LL ans[MAXN];
LL C[MAXN];
int lowbit(int x) {
return x & (-x);
}
int n;
void add(int x, int d) {
while(x <= n) {
C[x] += d;
x += lowbit(x);
}
}
LL Sum(int x) {
LL s = 0;
while(x > 0) {
s += C[x];
x -= lowbit(x);
}
return s;
}
struct GCD {
int l, r, val;
};
GCD gnum[MAXN * 30];
bool cmp2(GCD a, GCD b) {
return a.r < b.r;
}
int main()
{
int m;
while(scanf("%d%d", &n, &m) != EOF) {
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
RMQ_init(n); int top = 0;
for(int i = 1; i <= n; i++) {
int j = i;
while(j >= 1) {
int v = Query(j, i);
int l = 1, r = j, next;
gnum[top].l = j; gnum[top].r = i; gnum[top].val = v;
//cout << gnum[top].l << ' ' << gnum[top].r << ' ' << gnum[top].val << endl;
top++;
while(r >= l) {
int mid = (l + r) >> 1;
if(Query(mid, i) == v) {
next = mid;
r = mid - 1;
}
else {
l = mid + 1;
}
}
j = next - 1;
}
}
for(int i = 1; i <= m; i++) {
scanf("%d%d", &num[i].l, &num[i].r);
num[i].id = i;
}
sort(num + 1, num + m + 1, cmp1);
sort(gnum, gnum + top, cmp2);
int j = 0; CLR(C, 0); lp.clear();
for(int i = 1; i <= m; i++) {
while(j < top && gnum[j].r <= num[i].r) {
int v = gnum[j].val;
if(lp[v]) {
add(lp[v], -1);
}
lp[v] = gnum[j].l;
add(lp[v], 1);
j++;
}
ans[num[i].id] = Sum(num[i].r) - Sum(num[i].l - 1);
}
for(int i = 1; i <= m; i++) {
printf("%lld\n", ans[i]);
}
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <cstdlib>
#define ll o<<1
#define rr o<<1|1
#define CLR(a, b) memset(a, (b), sizeof(a))
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e5 + 10;
const int INF = 1e9 + 10;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int MOD = 1e9 + 7;
void add(LL &x, LL y) { x += y; x %= MOD; }
int a[20000 + 10];
int main()
{
int t;
while(scanf("%d", &t) != EOF) {
while(t--) {
int n; scanf("%d", &n);
int sum = 0;
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
sum += a[i];
}
if(sum != n * (n - 1)) {
printf("F\n");
continue;
}
sort(a + 1, a + n + 1);
sum = 0; int s = 0;
bool flag = true;
for(int i = n; i >= 1; i--) {
s += a[i];
sum += 2 * (i - 1);
if(s > sum) {
flag = false; break;
}
}
printf(flag ? "T\n" : "F\n");
}
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <cstdlib>
#define ll o<<1
#define rr o<<1|1
#define CLR(a, b) memset(a, (b), sizeof(a))
using namespace std;
typedef unsigned long long LL;
typedef pair<int, int> pii;
const int MAXN = 2e5 + 10;
const int INF = 1e9 + 10;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int MOD = 1e9 + 7;
void add(LL &x, LL y) { x += y; x %= MOD; }
int main()
{
LL n, m;
while(scanf("%llu%llu", &m, &n) != EOF) {
LL sum = floor(m * m * 1.0 / 4);
printf(n >= sum ? "T\n" : "F\n");
}
return 0;
}
H
思路:二分套個
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <cstdlib>
#define ll o<<1
#define rr o<<1|1
#define CLR(a, b) memset(a, (b), sizeof(a))
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e5 + 10;
const int INF = 1e9 + 10;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int MOD = 1e9 + 7;
void add(LL &x, LL y) { x += y; x %= MOD; }
int a[MAXN];
int Amin[MAXN][20];
void RMQ_init(int N) {
for(int i = 1; i <= N; i++)
Amin[i][0] = a[i];
for(int j = 1; (1<<j) <= N; j++) {
for(int i = 1; i + (1<<j)-1 <= N; i++)
Amin[i][j] = min(Amin[i][j-1], Amin[i+(1<<(j-1))][j-1]);
}
}
int Query(int L, int R) {
int k = 0;
while((1<<(k+1)) <= R-L+1) k++;
return min(Amin[L][k], Amin[R-(1<<k)+1][k]);
}
int Next[MAXN];
int main()
{
int t; scanf("%d", &t);
while(t--) {
int n; scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
RMQ_init(n);
for(int i = 1; i <= n; i++) {
int l = i + 1, r = n, pos = -1;
while(r >= l) {
int mid = l + r >> 1;
if(Query(l, mid) < a[i]) {
pos = mid;
r = mid - 1;
}
else {
l = mid + 1;
}
}
Next[i] = pos;
}
int m; scanf("%d", &m);
while(m--) {
int l, r; scanf("%d%d", &l, &r);
int ans = a[l];
int pos = l;
for(;;) {
pos = Next[pos];
if(pos > r || pos == -1) break;
ans %= a[pos];
}
printf("%d\n", ans);
}
}
return 0;
}
I
題意:求解補圖最短路。
前面到達的點後面就沒有用了,那就維護兩個集合,一個當前點可以到達且沒有被用過,一個當前點不可以到達且沒有被用過。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <cstdlib>
#define ll o<<1
#define rr o<<1|1
#define CLR(a, b) memset(a, (b), sizeof(a))
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 2e5 + 10;
const int INF = 1e9 + 10;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int MOD = 1e9 + 7;
void add(LL &x, LL y) { x += y; x %= MOD; }
vector<int> G[MAXN];
int d[MAXN];
set<int> use, have;
set<int> :: iterator it;
int n;
int ans[MAXN];
void Solve(int s) {
queue<int> Q; Q.push(s); CLR(d, INF);
d[s] = 0; have.clear(); use.clear();
for(int i = 1; i <= n; i++) {
if(i != s) {
have.insert(i);
}
}
while(!Q.empty()) {
int u = Q.front(); Q.pop();
for(int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if(!have.count(v)) continue;
have.erase(v); use.insert(v);
}
for(it = have.begin(); it != have.end(); ++it) {
Q.push(*it);
d[*it] = d[u] + 1;
}
have.swap(use); use.clear();
}
}
int main()
{
int t; scanf("%d", &t);
while(t--) {
int m; scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) G[i].clear();
while(m--) {
int u, v; scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
int s; scanf("%d", &s); Solve(s);
int top = 0;
for(int i = 1; i <= n; i++) {
if(i == s) continue;
ans[top++] = (d[i] != INF ? d[i] : -1);
}
for(int i = 0; i < top; i++) {
if(i > 0) printf(" ");
printf("%d", ans[i]);
}
printf("\n");
}
return 0;
}
J
思路:我們處理出
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <cstdlib>
#define ll o<<1
#define rr o<<1|1
#define CLR(a, b) memset(a, (b), sizeof(a))
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pii;
const int MAXN = 1e5 + 10;
const int INF = 1e9 + 10;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int MOD = 1e9 + 7;
void add(LL &x, LL y) { x += y; x %= MOD; }
struct Edge {
int from, to, next;
};
Edge edge[MAXN * 2];
int head[MAXN], edgenum;
void init() {CLR(head, -1); edgenum = 0;}
void addEdge(int u, int v) {
Edge E = {u, v, head[u]};
edge[edgenum] = E;
head[u] = edgenum++;
}
LL vs[MAXN];
int top;
int son[MAXN];
LL a[MAXN];
int id[MAXN];
void DFS(int u, int fa) {
son[u] = 1; id[u] = ++top; vs[top] = a[u];
for(int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].to;
if(v == fa) continue;
DFS(v, u);
son[u] += son[v];
}
}
int C[MAXN], n;
int lowbit(int x) {
return x & (-x);
}
void Update(int x, int d) {
while(x <= n) {
C[x] += d;
x += lowbit(x);
}
}
int Sum(int x) {
int s = 0;
while(x > 0) {
s += C[x];
x -= lowbit(x);
}
return s;
}
struct Node{
int l, r;
LL h;
};
Node num[MAXN];
bool cmp2(Node a, Node b){
return a.h < b.h;
}
int in[MAXN];
vector<pii> G;
vector<pii> :: iterator it;
bool cmp1(pii a, pii b){
return a.first < b.first;
}
int main()
{
int t, kcase = 1; scanf("%d", &t);
while(t--) {
LL k; scanf("%d%lld", &n, &k);
init();
for(int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
in[i] = 0;
}
for(int i = 0; i < n - 1; i++) {
int u, v;
scanf("%d%d", &u, &v);
addEdge(u, v);
in[v]++;
}
int root;
for(int i = 1; i <= n; i++) {
if(in[i] == 0) {
root = i; break;
}
}
top = 0; DFS(root, -1);
G.clear();
for(int i = 1; i <= top; i++) {
G.push_back(pii(vs[i], i));
}
sort(G.begin(), G.end(), cmp1);
for(int i = 1; i <= n; i++) {
num[i].l = id[i];
num[i].r = id[i] + son[i] - 1;
num[i].h = k / a[i];
}
sort(num + 1, num + n + 1, cmp2);
LL ans = 0; CLR(C, 0); it = G.begin();
for(int i = 1; i <= n; i++) {
while(it != G.end() && it->first <= num[i].h) {
Update(it->second, 1);
it++;
}
ans += Sum(num[i].r) - Sum(num[i].l - 1);
}
for(int i = 1; i <= n; i++) {
if(a[i] * a[i] <= k) {
ans--;
}
}
printf("%lld\n", ans);
}
return 0;
}