这天的题目没有名字,就以 A,B,C 分别代表 T1,T2,T3 吧。
A
题意
平面上给出
思路
参照 BZOJ2178 ,将横坐标看作自变量,直线 x=a 交圆环的长度为
代码
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN=220;
const int INF=1E7;
const double EPS=5E-4;
struct Ring
{
int x, y, R, r;
} a[MAXN];
struct Range
{
double l, r;
Range() {}
Range(double a, double b): l(a), r(b) {}
bool operator < (const Range& rhs) const
{
return l<rhs.l;
}
} b[2*MAXN];
int n;
inline double f(double x)
{
int m=0;
for (int i=1; i<=n; i++)
{
double d=fabs(x-a[i].x);
if (a[i].r<=d&&d<=a[i].R)
{
double q=sqrt(a[i].R*a[i].R-d*d);
b[++m]=Range(a[i].y-q, a[i].y+q);
}
else if (d<=a[i].r)
{
double p=sqrt(a[i].r*a[i].r-d*d);
double q=sqrt(a[i].R*a[i].R-d*d);
b[++m]=Range(a[i].y-q, a[i].y-p);
b[++m]=Range(a[i].y+p, a[i].y+q);
}
}
sort(b+1, b+m+1);
double L=-INF, R=-INF, s=0;
for (int i=1; i<=m; i++)
{
if (b[i].l>R) s+=R-L, L=b[i].l;
R=max(R, b[i].r);
}
s+=R-L;
return s;
}
inline double simpson(double l, double r)
{
double mid=(l+r)/2;
return (f(l)+4*f(mid)+f(r))*(r-l)/6;
}
double asr(double l, double r, double eps, double ans)
{
double mid=(l+r)/2;
double L=simpson(l, mid), R=simpson(mid, r);
if (fabs(L+R-ans)<=15*eps) return L+R+(L+R-ans)/15;
return asr(l, mid, eps/2, L)+asr(mid, r, eps/2, R);
}
int main()
{
// freopen("A.in", "r", stdin);
// freopen("A.out", "w", stdout);
scanf("%d", &n);
double L=INF, R=-INF;
for (int i=1; i<=n; i++)
{
scanf("%d%d%d%d", &a[i].x, &a[i].y, &a[i].R, &a[i].r);
L=min(L, (double)a[i].x-a[i].R); R=max(R, (double)a[i].x+a[i].R);
}
printf("%.3lf\n", asr(L, R, EPS, simpson(L, R)));
return 0;
}
B
题意
在平面上由原点
思路
应该可以推组合的式子,可是我并不会,所以我选择找规律。
暴力 DP 打表后得出规律,答案为
代码
#include <cstdio>
const int MAXN=1100000;
const int N=1000000;
const int MOD=998244353;
int fac[MAXN];
void exgcd(int a, int b, int& x, int& y)
{
if (b==0) x=1, y=0;
else exgcd(b, a%b, y, x), y-=a/b*x;
}
inline int inv(int a)
{
int x, y;
exgcd(a, MOD, x, y);
return (x%MOD+MOD)%MOD;
}
inline int C(int n, int m)
{
return 1ll*fac[n]*inv(1ll*fac[m]*fac[n-m]%MOD)%MOD;
}
inline int calc(int x, int y, int n)
{
if (x<-n||x>n||y<-n||y>n||(n-x-y)%2==1) return 0;
return 1ll*C(n, (n-x-y)/2)*C(n, (n+x-y)/2)%MOD;
}
int main()
{
// freopen("B.in", "r", stdin);
// freopen("B.out", "w", stdout);
int T;
scanf("%d", &T);
fac[0]=1;
for (int i=1; i<=N; i++) fac[i]=1ll*fac[i-1]*i%MOD;
while (T--)
{
int x, y, r;
scanf("%d%d%d", &x, &y, &r);
printf("%d\n", calc(x, y, r));
}
return 0;
}
C
题意
有
思路
考虑
代码
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN=110000;
const int INF=0X3F3F3F3F;
int a[MAXN];
int main()
{
// freopen("C.in", "r", stdin);
// freopen("C.out", "w", stdout);
int n, k;
scanf("%d%d", &n, &k);
for (int i=1; i<=n; i++) scanf("%d", &a[i]);
long long ans=0;
for (int i=1; i<=n; i++) ans+=a[i];
for (int i=1; i<=k; i++)
{
int cnt=0, mn=INF;
for (int j=i; j<=n; j+=k)
if (++cnt&1) mn=min(mn, a[j]);
if (cnt&1) ans-=mn;
}
printf("%lld\n", ans);
return 0;
}