题意:
爱丽丝有一块画布,最初是白色的,她想在上面画画。
Alice将执行n个操作,有两种类型的操作:
选择一个坐标(x,y),然后绘制一个以(x,y)为中心,边长为2的正方形,操作完成后该区域将变为黑色。
选择一个坐标(x,y),然后绘制以(x,y)为圆心,半径为1的圆的范围,操作完成后该区域变为黑色。
经过n次操作后,Alice想知道画布黑色部分的周长。
思路:
我们发现绘制圆和正方形只会影响四个方格,因此我们可以将其的影响先记录于每个方格中,然后最后遍历所有方格算出总周长。
对于每个方格我们需要知道的有,有无正方形对其产生影响,有无圆对其产生影响,方格的四条边是否处于某个图形之内。
有以下几个注意事项:
1.圆和正方形同时对方格产生影响时,正方形优先
2.正方形的影响是,未被包裹于图形中方格边的数量(注意需要判断相邻方格,防止出现两个正方形拼起来依然计算中间边长的情况)
代码:
//#include<bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <cstring>
#include<vector>
#include<queue>
#include<stack>
#include<bitset>
#include<set>
#include<map>
#include <math.h>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <vector>
//#include <unordered_set>
//#include <unordered_map>
#include <string>
#include <stack>
#include <cassert>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
using db = double;
typedef pair<ll, ll> pll;
#define edl '\n'
#define SPO(n) fixed << setprecision(n)
const double PI = acos(-1);
#define MAXN 100005
ll MAX = 0x3f3f3f3f3f3f3f3fll;
ll MIN = -MAX;
const int mod = 998244353;
const int N = 1e6 + 10;
ll fc[N], nn[N], NN[N];
ll n, m;
string s;
// 欧拉降幂
int phi(int n)
{
int res = n;
for (int i = 2; i * i <= n; i++)
{
if (n % i == 0)
{
res = res - res / i; // 不能是res*(1-1/i);
while (n % i == 0)
n /= i;
}
}
if (n > 1)
res = res - res / n;
return res;
}
// 快速幂优化
ll quick_pow(ll a, ll b, ll md)
{
ll ans = 1;
// ll pp = phi(md);
// if(b >= pp) b = b % pp + pp;
while (b)
{
if (b & 1)
ans = (ans * a) % md;
b >>= 1;
a = (a * a) % md;
}
return ans;
}
// 逆元函数 公式为 (a/b)%mod=(a*b^(mod-2))%mod
ll inv(ll a, ll b, ll md)
{
return (a * quick_pow(b, md - 2, md)) % md;
}
/***
注意事项 逆元函数的使用 a必须能整除b 并且mod为质数
**/
void CC(ll md)
{
fc[0] = nn[0] = NN[0] = 1;
for (int i = 1; i <= N - 2; i++)
fc[i] = fc[i - 1] * i % md;
NN[N - 2] = quick_pow(fc[N - 2], md - 2, md);
for (int i = N - 2 - 1; i >= 1; i--)
NN[i] = NN[i + 1] * (i + 1) % md;
for (int i = 1; i <= N - 2; i++)
nn[i] = NN[i] * fc[i - 1] % md;
}
ll C(ll n, ll m)
{
if (n < m || n < 0 || m < 0)
return 0;
return fc[n] * NN[m] % mod * NN[n - m] % mod;
}
struct QWQ
{
ll s1,s2,s3,s4;
ll ok;
ll sum;
ll sum1;
}a[1000][1000];
ll op;
map<pair<ll,ll>,ll>mp1;
map<pair<ll,ll>,ll>mp2;
ll x,y;
void Solve()
{
cin >> n;
for(int i = 1; i <= n; i ++ )
{
cin >> op;
if(op == 1)
{
cin >> x >> y;
x += 200;
y += 200;
if(mp1[{x,y}]) continue;
mp1[{x,y}] = 1;
a[x][y].ok = a[x + 1][y].ok = a[x + 1][y + 1].ok = a[x][y + 1].ok = 1;
a[x][y].s2 = a[x][y].s3 = 1;
a[x + 1][y].s1 = a[x + 1][y].s2 = 1;
a[x + 1][y + 1].s1 = a[x + 1][y + 1].s4 = 1;
a[x][y + 1].s4 = a[x][y + 1].s3 = 1;
a[x][y].sum1 ++;
a[x + 1][y].sum1 ++;
a[x][y + 1].sum1 ++;
a[x + 1][y + 1].sum1 ++;
}
else
{
cin >> x >> y;
x += 200;
y += 200;
if(mp2[{x,y}]) continue;
mp2[{x,y}] = 1;
a[x][y].ok = a[x + 1][y].ok = a[x + 1][y + 1].ok = a[x][y + 1].ok = 1;
a[x][y].s2 = a[x][y].s3 = 1;
a[x + 1][y].s1 = a[x + 1][y].s2 = 1;
a[x + 1][y + 1].s1 = a[x + 1][y + 1].s4 = 1;
a[x][y + 1].s4 = a[x][y + 1].s3 = 1;
a[x][y].sum ++;
a[x + 1][y].sum ++;
a[x][y + 1].sum ++;
a[x + 1][y + 1].sum ++;
}
}
ll ans1,ans2;
ans1 = ans2 = 0;
for(int i = 100; i <= 400; i ++ )
{
for(int j = 100; j <= 400; j ++ )
{
if(a[i][j].ok)
{
ll sum = a[i][j].s4 + a[i][j].s1 + a[i][j].s3 + a[i][j].s2;
if(sum == 4) continue;
if(a[i][j].sum1)
{
if(!a[i][j].s4)
{
int xx = i;
int yy = j - 1;
if(a[xx][yy].sum1 && !a[xx][yy].s2) ;
else ans1 ++;
}
if(!a[i][j].s1)
{
int xx = i - 1;
int yy = j;
if(a[xx][yy].sum1 && !a[xx][yy].s3) ;
else ans1 ++;
}
if(!a[i][j].s2)
{
int xx = i;
int yy = j + 1;
if(a[xx][yy].sum1 && !a[xx][yy].s4) ;
else ans1 ++;
}
if(!a[i][j].s3)
{
int xx = i + 1;
int yy = j;
if(a[xx][yy].sum1 && !a[xx][yy].s1) ;
else ans1 ++;
}
}
else if(a[i][j].sum) ans2 = (ans2 + inv(1,sum,mod)) % mod;
}
}
}
cout << ans1 << " " << ans2 << edl;
}
int main()
{
std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
//#ifndef ONLINE_JUDGE
//freopen("cin.txt","r",stdin);
//freopen("cout.txt","w",stdout);
//#endif
ll t = 1;
//cin >> t;
// 组合数
CC(mod);
while(t -- )
Solve();
return 0;
}