SRM 573

见过几次坐标旋转的,还是没掌握到精髓啊,完全没往这边想。


这题的转变很巧妙。旋转了45度,每步就变成(x+1,y+1),(x+1,y-1),(x-1,y+1),(x-1,y-1)四种选择。

这样每一步x和y都会变化,就可以独立分开考虑了。


#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>

using namespace std;

class WolfPack {
public:
	int calc(vector<int> , vector<int> , int);
};
long long pmod = 1000000007;
vector<long long> x, y;
long long ba[100005], rba[100005];
long long pwmd(long long a, long long k) {
	long long ret = 1;
	while (k) {
		if (k & 1)
			ret = a * ret % pmod;
		a = a * a % pmod;
		k >>= 1;
	}
	return ret;
}
void pre() {
	int i;
	ba[0] = rba[0] = 1;
	ba[1] = rba[1] = 1;
	for (i = 2; i < 100005; ++i) {
		ba[i] = ba[i - 1] * i % pmod;
		rba[i] = rba[i - 1] * pwmd(i, pmod - 2) % pmod;
	}
}
long long C(int n, int k) {
	return ba[n] * rba[k] % pmod * rba[n - k] % pmod;
}
int WolfPack::calc(vector<int> xx, vector<int> yy, int m) {
	int i, k;
	int n = xx.size();
	pre();
	x.clear();
	y.clear();
	for (i = 0; i < n; ++i) {
		x.push_back(xx[i] + yy[i]);
		y.push_back(xx[i] - yy[i]);
	}
	long long ans1, ans2, p;
	sort(x.begin(), x.end());
	ans1 = 0;
	for (k = x[x.size() - 1] - m; k <= x[0] + m; k += 2) {
		p = 1;
		for (i = 0; i < x.size(); ++i) {
			long long r;
			r = m - abs(x[i] - k);
			if (r % 2)
				p *= 0;
			else {
				p *= C(m, r / 2);
				p %= pmod;
			}
		}
		ans1 += p;
		ans1 %= pmod;
	}
	sort(y.begin(), y.end());
	ans2 = 0;
	for (k = y[y.size() - 1] - m; k <= y[0] + m; k += 2) {
		p = 1;
		for (i = 0; i < y.size(); ++i) {
			long long r;
			r = m - abs(y[i] - k);
			if (r % 2)
				p *= 0;
			else {
				p *= C(m, r / 2);
				p %= pmod;
			}
		}
		ans2 += p;
		ans2 %= pmod;
	}
	return ans1 * ans2 % pmod;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值