牛客挑战赛44 题解
切T1+T2+T4。尤其T4我是唯一一个写正解切了,但一血被一个NTT卡常选手占了。
T1
发现答案只有\(3,5,7\)。
具体证明考虑\(p,p+2,p+4\)模\(3\)意义下互不相同,所以肯定存在一个为\(3\)的倍数。
T2
lj题目大意。
按照物理课上学的知识来分析一下。
跑个最短路求出每个点的电势,再判一下\(1\)和\(n\)是否连通、\(1\)是否电势最高、\(n\)是否电势最低,每条边连接的两边的点电势差是否为这条边的电压。
T3
正解真就min_25筛呗。。。自认为比赛时写不出min_25而且看有很多人切于是死活不肯写min_25筛。
这里的min_25筛还是只用算\(g\)不用算\(S\)的阉割版本。
using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define N 1000010
#define ll long long
ll n,sq;
int p[N],np;
bool inp[N];
ll w[N];
int m;
int id1[N],id2[N];
#define id(x) (x<=sq?id1[x]:id2[n/x])
ll g[N];
int main(){
freopen("in.txt","r",stdin);
scanf("%lld",&n),sq=sqrt(n);
for (int i=2;i<=sq;++i){
if (!inp[i])
p[++np]=i;
for (int j=1;j<=np && i*p[j]<=sq;++j){
inp[i*p[j]]=1;
if (i%p[j]==0)
break;
}
}
for (ll i=1;i<=n;){
ll j=n/(n/i),d=n/j;
w[++m]=d;
id(d)=m;
i=j+1;
}
for (int i=1;i<=m;++i)
g[i]=w[i]-1;
for (int i=1;i<=np;++i){
for (int j=1;j<=m && w[j]>=(ll)p[i]*p[i];++j){
ll d=w[j]/p[i],k=id(d);
g[j]-=g[k]-(i-1);
}
}
ll s=g[id(n)];
for (int k=1;k<=np;++k){
ll x=(ll)p[k]*p[k];
for (;x<=n;x*=p[k])
s++;
}
printf("%lld\n",s);
return 0;
}
T4
T5
由于题解没有放图出来,所以不知道怎么构造的。
T6
比赛之后才发现是一道水题??
考虑\(a_i^2=a_{i-1}^2+a_{i-2}^2+a_{i-3}^2+2(a_{i-1}a_{i-2}+a_{i-1}a_{i-3}+a_{i-2}a_{i-3})\),如果我们能维护连续的三个\(a_i^2\)和\(a_ia_i-1\)和\(a_i\),就可以写出个线性的递推式,然后就可以用矩阵乘法优化了。
后面的那个斐波拉契平方和,可以试着用矩阵乘法卡过去。题解做法是搬出通项然后一波乱推。最后\(\sqrt 5\)的问题用定义一个类似于复数的东西处理。
最后看到评论区有人说\(\sum_{i=1}^nF_i^2=F_nF_{n+1}\)???