你觉得我这种彩笔像是能去做省选题的样子吗?=w=
合肥人,做初中的屑安徽题,很正常吧。AH 也不知道为啥搞啥市赛啊区赛啊省赛啊就挺离谱的反正摆烂人也不想打┓( ´∀` )┏
2018
T1
签到题
//SIXIANG
#include <iostream>
#define MAXN 100000
#define LL long long
#define QWQ cout << "QWQ" << endl;
using namespace std;
int a[MAXN + 10];
int main() {
int n; cin >> n;
LL ans = 0;
for(int p = 1; p <= n; p++)
cin >> a[p];
for(int p = 1; p < n; p++)
ans += max(a[p], a[p + 1]);
cout << ans << endl;
}
很棒的题捏,一开始没有想出来,然后试图用暴力卡常结果就几个 ms 卡不过去(捂脸
首先我们先考虑如果 \(x\) 是完全平方数怎么做(因为部分分给了=w=),显而易见直接二分。
那么我们再考虑 \(x\) 不是完全平方数的做法。我们考虑题目中的式子 \(x = a^3b\)。我们要尽力求出一个 \(b\),最后的剩下的 \(\dfrac{x}{b}\) 就二分跑一遍就可以了。我们考虑一下性质,如果我们 \(b\) 做一个唯一分解,那么它的次数都小于等于 \(2\)。同时 \(b\) 显然不可能大于 \(\sqrt[4]{x}\)。我们通过这两点会发现 \(b\) 里面所有质因子都不大于 \(\sqrt[4]{x}\)。因而可以把 \(b\) 表示为 \(b=pq^2\)。\(a\) 必然不超过 \(\sqrt[3]{x}\)。
然后是一个比较人类智慧的操作 \(x\) 除掉所有 \(\sqrt[4]{x}\) 里面的素数,剩下的要么然是立方数,要么是 \(a = 1\) 的数字。我感觉这么智慧的操作可能是因为“\(b\) 里面所有质因子都不大于 \(\sqrt[4]{x}\)”(或者说伟大的人类智慧)。如果我们除掉这些质因数,肯定把 \(b\) 里面的质因数都除掉了一次。那么 \(b\) 肯定没了。那 \(a\) 呢?\(a\) 小于等于 \(\sqrt[4]{x}\) 的因子全没了。如果 \(a\) 的所有引子都是小于 \(\sqrt[4]{x}\) 的,那么 \(a = 1\),否则 \(a\) 为立方数。
有了这个奇妙的引理,那么这道题就不难做了,首先把小于等于 \(\sqrt[4]{1e18}\)(差不多是 32000) 的素数预处理出来,然后对 \(x\) 除掉里面的素数,最后对剩下的 \(x'\) 二分求立方根。然后用原来的 \(x\) 逝世有没有小于等于 \(\sqrt[4]{1e18}\) 的立方质因子 awa。
这个引理比较人类智慧,不过也不太算,比较简单
//SIXIANG
#include <cstdio>
#include <cmath>
#define MAXN 32000
#define LL long long
#define int long long
#define QWQ cout << "QWQ" << endl;
using namespace std;
bool vis[MAXN + 10];
int pri[MAXN + 10], tot = 0;
void prime() {
vis[1] = 1;
for(int p = 2; p <= MAXN; p++)
if(!vis[p]) {
pri[++tot] = p;
for(int i = p + p; i <= MAXN; i += p)
vis[i] = 1;
}
}
LL divide(LL x, LL lim) {
for(int p = 1; p <= tot; p++) {
if(pri[p] > lim) break;
int cnt = 0;
while(x % pri[p] == 0) x /= pri[p];
}
return x;
}
LL sqrt3(LL x) {
LL l = 1, r = 1e6, mid;
while(l <= r) {
mid = (l + r) >> 1;
if(mid * mid * mid < x) l = mid + 1;
else if(mid * mid * mid > x) r = mid - 1;
else return mid;
}
return 1;
}
signed main() {
prime();
LL x;
int T; scanf("%lld", &T);
while(T--) {
scanf("%lld", &x);
LL pk = 1;
LL sqrt4 = ceil(sqrt(sqrt(x)));
for(int p = 1; p <= tot; p++) {
if((LL)pri[p] > sqrt4) continue;
int cnt = 0;
while(x % pri[p] == 0) {
x /= pri[p];
cnt++;
if(cnt % 3 == 0)
pk *= pri[p];
}
}
printf("%lld\n", sqrt3(x) * pk);
}
}
T3
签到题,模拟题。
先排序,然后挨个尝试加入队列,如果加不进去就新开一个队列,最后统计人数最少的队列。显而易见,这是对的,证明日后补吧 =w=
//SIXIANG
#include <iostream>
#include <algorithm>
#include <queue>
#define MAXN 100000
#define QWQ cout << "QWQ" << endl;
using namespace std;
int a[MAXN + 10];
struct node {
int back, siz;
} que[MAXN + 10];
int main() {
int n; cin >> n;
for(int p = 1; p <= n; p++)
cin >> a[p];
sort(a + 1, a + n + 1);
int tot = 0;
for(int p = 1; p <= n; p++) {
bool homo = 0;
for(int i = 1; i <= tot; i++) {
if(que[i].back - a[p] == -1) {
que[i].back = a[p];
que[i].siz++;
homo = 1;
break;
}
}
if(!homo) que[++tot].back = a[p], que[tot].siz = 1;
}
int minn = 0x7f7f7f7f;
for(int p = 1; p <= tot; p++)
minn = min(minn, que[p].siz);
cout << minn << endl;
}
也可以用堆来优化到 O(nlogn),上面这个时间复杂度是玄学,最坏 $O(n^2)$,不过显然跑不满
T4
神仙题。
先考虑一下只有 \(1,2\) 的情况,这个时候必然是 \(1,2\) 交替的放,然后就显然对吧。
然后再考虑只有质数的情况,那么相邻两个必然不相同。那么我们的问题就是说有 \(n\) 个球然后每个球有个颜色相邻两个球颜色不同。
这个问题比现在这个题好做多了,但是我们先放在一边。
在考虑自然数的情况。我们考虑把它变成上面那个问题 \(n\le 300\),所以可以高一些好康的。
引理:如果 \(xy\) 为平方数,\(yz\) 为平方数,\(xz\) 也是平方数。
证明:显然把 =w=。
所以说我们可以枚举 \(i, j(i \not= j)\),如果 \(ij\) 为平方数,那么就并查集连一起,同一个并查集里面的看成一个颜色。
然后就可以愉快的 dp 啦~这才是本题最毒瘤的,zyf 巨佬说有某个合肥六中巨佬当年也卡在了这里所以我看题解不过分吧,心理平衡了(???
不难想到以颜色为阶段,设 \(f_i\) 为前 \(i\) 个颜色的合法方案数。但显然不行,因为合法方案可能由不合法的转移而来。所以我们加一维,\(f_{i, j}\) 代表前 \(i\) 个颜色 \(j\) 个相邻的数的方案。假设第 \(i\) 种颜色有 \(S_i\) 个球,每次转移会在其中新增 \(ad\) 个相邻数,抵消掉原来 \(su\) 个相邻数。转移到的状态就应该是 \(f_{i, j}\) 到 \(f_{i+1,j + ad - su}\)。
先考虑增加增加 \(ad\) 个相邻数。在
2017
T1
本来还以为是什么数学题,后来发现是暴力就没写了 =w=
抄原题,太屑了。这 FJ 一看就是 USACO 的,安徽人很负责的(•́へ•́╬)
很显然吧,跑 2 遍 dij 求出来权值为 \(P\) 与权值为 \(Q\) 的图上的最短路,然后对每条边 \((u, v)\),统计不在多少张图的最短路上,就是边权。再跑一遍最短路。
然后如何判断 \((u, v)\) 在不在最短路上?很简单 \(dis_u + val = dis_v\) 就是在最短路上。
不过由于这里面最短路是指当前节点到终点的最短路,所以要反向建图
#include <iostream>
#include <vector>
#include <cstring>
#include <queue>
#define MAXN 500000
using namespace std;
int k;
struct node {
int to, val[2];
node(int t, int p, int q) {
to = t, val[0] = p, val[1] = q;
}
bool operator < (const node &other) const {
return val[k] > other.val[k];
}
};
vector <node> gra[MAXN + 10], ngr[MAXN + 10];
bool vis[MAXN + 10];
int dis1[MAXN + 10], dis2[MAXN + 10], dis3[MAXN + 10];
void Dijkstra(int s, int *dis) {
for(int p = 1; p <= MAXN; p++)
dis[p] = 0x7f7f7f7f;
memset(vis, 0, sizeof(vis));
priority_queue <node> que;
que.push(node(s, 0, 0));
dis[s] = 0;
while(!que.empty()) {
node fr = que.top(); que.pop();
int u = fr.to;
if(vis[u]) continue;
vis[u] = 1;
for(int p = 0; p < gra[u].size(); p++) {
int v = gra[u][p].to;
if(dis[u] + gra[u][p].val[k] < dis[v]) {
dis[v] = dis[u] + gra[u][p].val[k];
if(!vis[v])
if(k == 0) que.push(node(v, dis[v], 0));
else que.push(node(v, 0, dis[v]));
}
}
}
}
int main() {
int n, m;
cin >> n >> m;
for(int p = 1, x, y, P, Q; p <= m; p++) {
cin >> y >> x >> P >> Q;
gra[x].push_back(node(y, P, Q));
}
k = 0, Dijkstra(n, dis1);
k = 1, Dijkstra(n, dis2);
int yyy = 0;
for(int u = 1; u <= n; u++) {
for(int p = 0; p < gra[u].size(); p++) {
int v = gra[u][p].to;
if(dis1[v] != dis1[u] + gra[u][p].val[0]) yyy++;
if(dis2[v] != dis2[u] + gra[u][p].val[1]) yyy++;
ngr[u].push_back(node(v, yyy, 0));
yyy = 0;
}
}
for(int p = 1; p <= n; p++)
for(int i = 0; i < ngr[p].size(); i++)
gra[p][i] = ngr[p][i];
k = 0, Dijkstra(n, dis3);
cout << dis3[1] << endl;
}
标签:AHOI,int,mid,sqrt,define,2018,2017,include,dis
From: https://www.cnblogs.com/thirty-two/p/16863162.html