5.23 NOI 模拟
$5.23\ NOI $模拟
\(T1\)简单的计算几何题
\(zjr:\)我当时没改,那么自己看题解吧
倒是有个简单的随机化方法(能获得\(72pts,\)正确性未知)\(:\)
随机两条切椭圆的平行线,然后统计内部点数,两个平行线经过微扰可以看成是一个四边形,那么可以保证相切要求
\(T2\)简单图论题
结论\(:\)由于是二分图,最后可以把边全部删完
那么我们的过程是,先把第一层能删的全部删完,复制,然后把第二层全部删完
我天真地以为直接模拟就好了,然后当出现环的时候,需要特殊考虑
对于环的情况,我们只需要相邻的不一样着删即可,按奇偶性删
附上因为\(ZZ\)错误而变得繁琐的代码
#include
#define MAXN 5000005
using namespace std;
bool vis[MAXN];
int w,h,res,du[MAXN];
vectorrd[MAXN];
int id(int x,int y)
{
return (x-1)*h+y;
}
int id1(int x,int y)
{
return (x-1)*h+y+id(w,h);
}
pair Make(int num)
{
int x=num/h+(num%h==0?0:1);
int y=(num%h==0?h:num%h);
return make_pair(x,y);
}
struct node
{
int opt,x,y,bel;
};
vectorAns;
struct NO
{
int x;
bool operator < (const NO&a)const
{
return du[x]>du[a.x];
}
};
multisetSt;
int main()
{
scanf("%d%d",&w,&h);
for(int i=1,opt;i<=w;i++)
{
for(int j=1;jx;
St.erase(St.begin());
if(du[now]%2==0||vis[now]) continue;
pairtu=Make(now);
Ans.push_back((node){1,tu.first,tu.second,0});
vis[now]=true;
// cout<<"Era: "<tu=Make(i);
Ans.push_back((node){1,tu.first,tu.second,((tu.first+tu.second)&1)});
}
}
// cout<<"--------------------------------------\n";
// for(int i=1;i<=h*w;i++)
// {
// if(!vis[i])cout<
\(T3\)
网格染色问题,可以比较显然的转化到有向图连边(曾经遇到过一次)
那么我们的边的连接方式形如\(i->j,j->i+j...\)
可以看出是一个斐波那契数列的形式,我们要需要对于每个点快速求出他是在哪个环里即可
一个比较常见的结论\(:Fibonacci\)数列在\(\mod 2^n\)下循环节是\(3\times 2^{n-1}\)
我们需要迅速转移出每个点的所在的环
考虑比较暴力的跳环并且标记,直接根号跳环,根号往后扫即可,\(O(2^\frac{n}{2}k)\)
比较\(nb\)的做法,复杂度\(O(nk)\)
我们\((x\% 2^0,y\% 2^0)\)所在环可以得到,那么我们可以得到\((x\% 2^1,y\% 2^1)\)
具体方法就是,对于每个环找一个标准点
我们每次模数乘二,环大小最多乘\(2,\)我们最多会有\(4\)种变化情况,我们枚举我们原来的长度一直往后跳\(len,2len...\)的长度,因为我们每个转移都是保证后\(k\)为相等,然后距离还是\(len\)的倍数,这样的话复杂度就可以达到优秀的\(O(nk)\)
哦日子哦日子哦日子
#include
#define P(x,y) ((1ll*x)<<31|y)
#define mode 998244353
using namespace std;
int a,b,c,n,m,k;
int x[1001],y[1001],z[1001];
int my_pow(int x,int y)
{
int cnt=1;
while(y)
{
if(y&1) cnt=1ll*cnt*x%mode;
x=1ll*x*x%mode;
y=(y>>1);
}
return cnt;
}
struct Mat{
int a[2][2];
friend Mat operator *(Mat a,Mat b)
{
Mat res;
memset(res.a,0,sizeof(res.a));
for(int i=0;i<2;++i)
{
for(int j=0;j<2;++j)
{
for(int k=0;k<2;++k)
{
res.a[i][j]=(1ll*a.a[i][k]%n*b.a[k][j]%n+res.a[i][j])%n;
}
}
}
return res;
}
}zy[10001];
unordered_map exis;
signed main()
{
scanf("%d %d %d",&n,&m,&k);
int w=n/2+2,len=n/2+2;
//对于根号分块
len=(1<