| 时间 | 名称 | 赛制 | 组别 | 得分 | 排名 | 
|---|---|---|---|---|---|
| 2022.10.25 | 2021牛客OI赛前集训营(第七场) | OI | 提高组 | 200/400 | 9 | 
注:买的去年的题,本地OI赛制,排名按当年的计算。
A.依依寺
为什么给的是  然而样例有  。
- 
特判掉 的情况后发现 仅仅是用来调控先后手关系的。 
- 
进一步的,我们只需要知道最多能拿多少个石子,按奇偶判断先手必胜或必败。 
- 
那么就会有两种取石子方案:A.先手取 ,然后 ;B.先手取 ,然后 。 
判断下是否存在一种方案使先手必胜即可。
时间复杂度 。
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int T;
    cin>>T;
    long long a,b,c;
    while(T--)
    {
        scanf("%lld %lld %lld",&a,&b,&c);
        if(!b && !c)
        {
            printf("Second\n");
            continue;
        }
        int lst=a&1;
        int tmp1=(1+((b-1>c)?c*2+1:(b-1)*2))&1,tmp2=(1+((c-1>b)?b*2+1:(c-1)*2))&1;
        if((b && (lst+tmp1)&1) || (c && (lst+tmp2)&1)) printf("First\n");
        else printf("Second\n");
    }
    return 0;
}
B.武义寺
考场打的 的状压然而数组开小了痛失 。
这里讲下正解公式是什么意思,然后发现考场居然没有想到(悲)。
设该数列最早在 位置出现 ,令 ,枚举 ,则前 个数的可行的方案:
既然位置 已经填了 ,对于 是不影响的,考虑倒着选数,位置 能选 个数(它后面全部的数和它本身),位置 本来能选 个数,但已经被位置 选了一个,于是也只能选 个数。以此类推,到了位置 发现它不能选本身(因为已经被位置 选了),只能选 个,它前面的数也都只能选 个。
因此得到前 个数的可行的方案(最后一步自行用等比数列求和公式推导):
答案即为:
最后要加上 的原因是当且仅当 与 一一对应时,。
时间复杂度 。
代码:
#include<bits/stdc++.h>
using namespace std;
#define inv(x) quick_pow(x,MOD-2)
const int MAXN=1e6+5;
const int MOD=998244353;
int fac[MAXN];
int quick_pow(int a,int b)
{
	int ret=1;
	while(b)
	{
		if(b&1) ret=(long long)ret*a%MOD;
		a=(long long)a*a%MOD,b>>=1;
	}
	return ret;
}
int main()
{
	int n;
	cin>>n;
	fac[0]=1;
	for(int i=1;i<=n;++i) fac[i]=(long long)fac[i-1]*i%MOD;
	int ans=0;
	for(int k=1;k<=n;++k) (ans+=(long long)(n-k+1)*fac[k]%MOD*(quick_pow(k+1,n-k)-quick_pow(k,n-k)+MOD)%MOD)%=MOD;
	(ans+=n+1)%=MOD;
    ans=(long long)ans*inv(fac[n])%MOD;
	cout<<ans;
	return 0;
}
C.依久依久
考场想到了正解但是没时间调了(考后花了5min就过了)
预处理发现在 以内的斐波那契数只有 个。
于是可以预处理出第 个斐波那契数 和 到 的前缀异或和。
每次对询问的区间 分块 中间这段已知,旁边两段继续递归下去。
当 间不存在斐波那契数时,设 为第一个小于 的斐波那契数,递归 。
时间复杂度 。
代码:
#include<bits/stdc++.h>
using namespace std;
const int n=86;
long long fib[n+1],sum[n+1];
int tmp=0;
long long work(long long l,long long r)
{
    if(l>r) return 0;
    int L=lower_bound(fib+1,fib+n+1,l)-fib,R=upper_bound(fib+1,fib+n+1,r)-fib-1;
    if(L>R)
    {
        long long ret=((r-l+1)&1)?fib[R]:0;
        ret^=work(l-fib[R],r-fib[R]);
        return ret;
    }
    long long ret=sum[R]^sum[L]^fib[L];
    ret=ret^work(l,fib[L]-1)^work(fib[R]+1,r);
    return ret;
}
int main()
{
    fib[1]=1,fib[2]=2;
    for(int i=3;i<=n;++i) fib[i]=fib[i-1]+fib[i-2];
    sum[1]=1,sum[2]=3;
    for(int i=3;i<=n;++i)
    {
        sum[i]=sum[i-1]^sum[i-2]^fib[i-2]^fib[i];
        if((fib[i-2]-1)&1) sum[i]^=fib[i-1];
    }
    int T;
    cin>>T;
    long long l,r;
    while(T--)
    {
        scanf("%lld %lld",&l,&r);
        printf("%lld\n",work(l,r));
    }
    return 0;
}
D.补幺梨
一道披着完全背包外衣的同余最短路题目……
设 ,则构建一个 个点的有向图。
跑完最短路后 表示余数为 (模 意义下)最小能得到的数。
答案即为 。
时间复杂度 ,最坏复杂度为 ,足以通过此题。
//后记&总结:考场心态还是蛮关键的,T2数组开小挂了10分,T3想到了正解但由于紧张没打出来,最后只能拿30分遗憾离场……应当合理分配时间,把时间留给能过的题。
笔者能力有限,有未述详尽或有误之处,欢迎指正。

 京公网安备 11010502036488号
京公网安备 11010502036488号