4.6 模拟赛小记
T1 猴子选大王
对于第一个子任务,看一下 luogu P8671 约瑟夫环,用 f 存当前所选个数下的答案下标,易推得公式 f[i] = (f[i - 1] + m) % i。(后记:当时看的一篇该题题解理解了,后来题解撤了??然后还是不太懂,可以看一下 oiwiki (虽然解释的依旧很水),以及知乎有一个证明。总之这个可以当做函数自己证明一下。感觉该式子的思路就是根据上一次的幸存者,对于这一次把新加入的人加入环中,然后找这次幸存者,在确定其在环中的位置。证明的话就注意和前面式子在环上的关系,以及转为环后的位置)。
怎么推得?正难则反,不妨倒推环中剩下的人数,从环中有一人、二人...一直到最后的答案,当环中有 n 个人时赢。这样就比较好推了(我们把编号整体减 1,这样方便取模):环中只剩一人:f[1] = 0,f[2] = (f[1] + m) % 2,f[3] = (f[2] + m) % 3....f[i] = (f[i - 1] + m) % i。可以理解为:f[i - 1] 表示前面那个没死啦,+m 即来更新一下在环中新位置,%i 来确定在环上的位置。
对于第二个子任务,当 m = 1 时,不难得到最后一个即为答案。
对于第三个子任务,可以模拟进行规律寻找。答案即找到这个数二进制下最高位 1,该数与这个 2 的幂之差乘二加一。太抽象了,具体见代码,还是建议自己手动模拟。
#include<bits/stdc++.h>
#define intt long long
using namespace std;
const intt N = 1e8 + 10;
intt n, m;
intt vis[N];
void did1()
{
intt sum = 0;
for(int i = 2; i <= n; i ++ ) sum = (sum + m) % i;
cout << sum + 1;
}
void did2() {cout << n;}
intt bpow(intt a, intt b)
{
intt ans = 1;
while(b)
{
if(b % 2) ans = ans * a;
a = a * a;
b /= 2;
}
return ans;
}
void did3()
{
intt i = 0, nn = n;
while(nn)
{
nn >>= 1;
i ++;
}
i --;
printf("%lld", (n - bpow(2, i)) * 2 + 1);
}
signed main()
{
scanf("%lld%lld", &n, &m);
if(n <= 10000000)
{
did1();
return 0;
}
if(m == 1)
{
did2();
return 0;
}
if(m == 2)
{
did3();
return 0;
}
}
T2 好人与坏人
还是和约瑟夫问题有关,在早期我甚至做过,居然不会写了,属实难绷。
模拟每次数的数,然后暴力算出每次死的人,看看好人死没死,然后如果坏人都死光光了就赢了。当时的思路过于暴力...每次算谁死了没必要暴力计算,直接模一下就好。
#include<bits/stdc++.h>
using namespace std;
int k, n, m;
int main()
{
scanf("%d", &k);
n = 2 * k;
while(1)
{
int a = 0;
m ++;
for(int i = 0; i < k; i ++ )
{
a = (a + m - 1) % (n - i);
if(a < k) break;
if(i == k - 1)
{
printf("%d", m);
return 0;
}
}
}
}
T3 蚂蚁上树 洛谷:P2907 [USACO08OPEN]Roads Around The Farm S
小红题,当时写挂是因为读错题力。需要反思,我记得当天这个红题调了一节课,羞耻捏。错误原因是读错题理解错题意了。感觉因为读错题而错的问题已经很多次了,感觉需要更加认真。。。(当时以为两窝蚂蚁,分为两窝之后一窝就可以不要了???
然后就是递归,每次的结果为分为两窝的结果,一直分,直到分不了为止。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n, k;
int ans(int q)
{
if((q - k) % 2 || q < 2 + k) return 1;
else return ans((q - k) / 2) + ans((q - k) / 2 + k);
}
signed main()
{
scanf("%lld%lld", &n, &k);
printf("%lld", ans(n));
return 0;
}
T4 能量石
至今不会。听说正解是斜率优化,似乎没人做。
T5 最短周游
至今不会。正解是分治 + st表。
后记废话:当天模拟赛时很智障的。尤其是在知道自己做的是红加橙的大水题后。也发现很多基础问题没有落实好,而且我本身,也确实,不喜欢写递归。从自身找原因的话确实有很多问题好吧。就这样吧。慢慢积累慢慢进步,落实基础。别着急,别和别人比。