2022牛客五一集训派对day1(E, G思维+数学)

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-E+F=1.

V:正多边形上的点有n个,内部的点有C\textrm{}_{n}^{4}个,因为两条直线相交于一点,两条直线有4个顶点,所以4点确定一个内部的点.总共有C\textrm{}_{n}^{4}+n个点.

E:C\textrm{}_{n}^{2}+2*C\textrm{}_{n}^{4}

可得F=C\textrm{}_{n}^{2}+C\textrm{}_{n}^{4}-n-1

#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();
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值