不知不觉周末了,发现自己没有干什么事,NOIP怎么办啊?Mr.Lin的题出好了,个人认为比较良(hei)心,希望以后做到这套题的人不要骂我吧233。
题解就贴在这里好了:
T1 K-D tree裸题,本蒟蒻刚学会K-D tree想练练手,于是和暴力大战了一天之后,终于把std写出来了QAQ
题解是直接建KD树,因为我加强了数据,所以表示我们要重构这棵树(不重构过了得真是强orz我把我没有重构的跑直接RE..),判圆我们可以用欧几里得距离评估,是一个很棒的东西,感谢Claris~
欧几里得距离评估:
max((X−pMaxX)2,(X−pMinX)2)+max((Y−pMaxY)2,(Y−pMinY)2)≤R2
此时该矩形区域被圆完全包含
max(max(X−pMaxX,pMinX−X),0)2+max(max(Y−pMaxY,pMinY−Y),0)2>R2
此时该矩形区域与圆无交集
根据这个来更新就好了~
T2 字符串水题,就是求一个字符串的最小表达,我们记录
i
为当前开始的最优位置,
分情况讨论
s[i+k]>s[j+k]
时,我们用
j
来更新答案,并看看
否则的话 则当前这一段长度为
k
的区间我们都不能作为开头,因为并不优,所以
题解就那么多,不懂得看程序吧,包里应该有ovo~
另外贴一道NOIP2009的题解,蒟蒻NOIP题都玩不溜啊
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 50000
#define ll long long
ll prime[N+10],pcnt;
ll p[N],a0,a1,b0,b1;
ll cnt[N];
ll num[3];
bool flag[N+10];
void pre()
{
for (ll i = 2 ; i <= N ; ++i)
{
if (!flag[i]) prime[++pcnt] = i;
for (ll j = 1 ; j <= pcnt && i * prime[j] <= N ; ++j)
{
flag[i*prime[j]] = 1;
if (i % prime[j] == 0) break;
}
}
}
void factor(ll x)
{
ll m = sqrt(x);
for (int i = 1 ; i <= pcnt && prime[i] <= m ; ++i)
{
if (x % prime[i] == 0) p[++p[0]] = prime[i],cnt[p[0]]++,x /= prime[i];
while (x % prime[i] == 0)
{
cnt[p[0]]++;
x /= prime[i];
}
if (x == 1) break;
}
if (x ^ 1) p[++p[0]] = x,cnt[p[0]]++;
}
int main()
{
#ifdef VictorXie
freopen("son.in","r",stdin);
#endif
ll t;
pre();
scanf("%lld",&t);
while (t--)
{
ll ans = 1;
bool flag = 0;
scanf("%lld%lld%lld%lld",&a0,&a1,&b0,&b1);
memset(p,0,sizeof(p));
memset(cnt,0,sizeof(cnt));
if (b1 % a1) {puts("0");continue;}
num[0] = b1/b0,num[1] = b1/a1,num[2] = a0/a1;
factor(num[1]);
for (int i = 1 ; i <= p[0] ; ++i)
if (num[2] % p[i] == 0) cnt[i] = 0;
for (int i = 1 ; i <= p[0] ; ++i)
if (num[0] % p[i] == 0)
if (!cnt[i]) {flag = 1;break;}
else cnt[i] = 0;
if (flag) {puts("0");continue;}
for (int i = 1 ; i <= p[0] ; ++i)
ans *= (cnt[i]+1);
printf("%lld\n",ans);
}
}