E.
题目大意:给定一个n * m的网格,相邻的网格之间有一条路径,另外还有k对点存在路径,求出一个方案可以从起点(1,1)开始途径所有的点至少一次使得路径长度最短,每条路径的长度为1.
解题思路:
首先,给结论:如果n*m为偶数,那么最短路径是n*m,即可以一次性不重复地走完所有的格子.当n*m为奇数时,当存在一条路径从(x1,y1)到(x2,y2)(x1+y1和x2+y2均为偶数)时,那么路径长度为n*m, 否则是n*m+1.
证明:
1.首先我们假设只有相邻的网格是有路径的.我们将整个网格看成国际象棋棋盘,假设起点(1,1)为黑色,如果n*m为偶数,那么棋盘黑色方格数和白色方格数相等.每次走动时我们只往相邻的格子走,那么所在的格子的颜色一定会改变.倒数第二步一定是白色格子,所以一定存在一种方案使得当前格子的颜色按照黑->白->黑->...->白的顺序行走.但是当n*m为奇数时,一定会多出一格黑色,按照最优的走法,最后到达的一定是黑色格子,所以一定要再经过一次已经经过的白色,才能到达起点.
2.那么我们考虑用其他的路径来优化解,对于n*m为奇数的情况,我们只需满足有一次变换是黑->黑即可,这样我们就可以把多出的那个黑色给走掉了.
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <map>
#include <vector>
//#define LOCAL
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define PII pair<int, int>
#define PDI pair<double, int>
#define int long long
#define ll long long
#define debug(a) cout << #a << "=" << a << endl;
#define all(x) (x).begin(), (x).end()
#define sd(x) scanf("%d", &(x))
#define sddd(x, y, z) scanf("%d%d%d", &(x), &(y), &(z))
using namespace std;
signed main() {
#ifdef LOCAL
freopen("input.in", "r", stdin);
freopen("output.out", "w", stdout);
#endif
IOS;
int T;
cin >> T;
while (T--) {
int n, m, k;
cin >> n >> m >> k;
int ok = ((n * m) % 2);
for (int i = 1; i <= k; ++i) {
int x1, x2, y1, y2;
cin >> x1 >> y1 >> x2 >> y2;
ok &= !((x1 != x2 || y1 != y2) && (x1 + y1) % 2 == 0 && (x2 + y2) % 2 == 0);
}
cout << n * m + ok << "\n";
}
}
G
题目大意:给定一个正多边形(奇数边),将每两个点相连,求出最后划分的区域数是多少.
解题思路:首先,有欧拉定理:.
V:正多边形上的点有n个,内部的点有个,因为两条直线相交于一点,两条直线有4个顶点,所以4点确定一个内部的点.总共有个点.
E:
可得
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,a,n) for(int i=n;i>=a;i--)
#define fors(i,a,n) for(int i=0;i<n;i++)
#define lowbit(x) x&(-x)
#define pb push_back
#define SZ(v) ((int)v.size())
#define fs first
#define sc second
typedef long long ll;
typedef double db;
typedef pair<int,int> PII;
ll gcd(ll a, ll b) {ll temp;if(a<b)swap(a,b);while(b!=0){temp=a%b;a=b;b=temp;}return a;}
ll lcm(ll a,ll b){return a*b/gcd(a,b);}
const int N = 100010;
const ll mod=1e9+7;
namespace NUM
{
constexpr int P = (int)1e9+7; // to do
template<class T> T power(T a, long long b) { T r = 1; for (; b > 0; b >>= 1, a *= a) if (b & 1) r *= a; return r; }
inline int norm(int x) { if (x < 0) x += P; else if (x >= P) x -= P; return x; }
struct node
{
int x;
node(int x = 0) : x(norm(x)) {}
int val() const { return x; }
node operator-() const { return node(norm(P - x)); }
node inv() const { assert(x != 0); return power(*this, P - 2); }
node& operator+=(const node& rhs) { x = norm(x + rhs.x); return *this; }
node& operator-=(const node& rhs) { x = norm(x - rhs.x); return *this; }
node& operator*=(const node& rhs) { x = 1LL * x * rhs.x % P; return *this; }
node& operator/=(const node& rhs) { return *this *= rhs.inv(); }
friend node operator+(const node& lhs, const node& rhs) { node res = lhs; res += rhs; return res; }
friend node operator-(const node& lhs, const node& rhs) { node res = lhs; res -= rhs; return res; }
friend node operator*(const node& lhs, const node& rhs) { node res = lhs; res *= rhs; return res; }
friend node operator/(const node& lhs, const node& rhs) { node res = lhs; res /= rhs; return res; }
bool operator== (const node& rhs) { return x == rhs.x; }
bool operator!= (const node& rhs) { return x != rhs.x; }
// operator int() { return x; }
};
istream& operator>>(istream& is, node& z) { is >> z.x; z.x = norm(z.x); return is; }
ostream& operator<<(ostream& os, const node& z) { os << z.x; return os; }
}
using INT = NUM::node;
void solve(){
INT n;cin >> n;
INT ans = (n-1) * (n-2) *(n*n - 3*n +12) /24;
cout << ans << endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t = 1;
//cin >> t;
while(t--){
solve();
}
}