zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 41

    Educational Codeforces Round 41 

    D. Pair Of Lines

    考虑先把凸包找出来,如果凸包上的点数大于(4)显然不存在解,小于等于(2)必然存在解

    否则枚举凸包上两个点连线,判断剩余点能否被一条线覆盖即可

    view code
    #pragma GCC optimize("O3")
    #pragma GCC optimize("Ofast,no-stack-protector")
    #include<bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define endl "
    "
    #define LL long long int
    #define vi vector<int>
    #define vl vector<LL>
    #define all(V) V.begin(),V.end()
    #define sci(x) scanf("%d",&x)
    #define scl(x) scanf("%lld",&x)
    #define scs(s) scanf("%s",s)
    #define pii pair<int,int>
    #define pll pair<LL,LL>
    #ifndef ONLINE_JUDGE
    #define cout cerr
    #endif
    #define cmax(a,b) ((a) = (a) > (b) ? (a) : (b))
    #define cmin(a,b) ((a) = (a) < (b) ? (a) : (b))
    #define debug(x)  cerr << #x << " = " << x << endl
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    template <typename T> vector<T>& operator << (vector<T> &__container, T x){ __container.push_back(x); return __container; }
    template <typename T> ostream& operator << (ostream &out, vector<T> &__container){ for(T _ : __container) out << _ << ' '; return out; }
    const int MAXN = 2e5+7;
    pii V(const pii &A, const pii &B){ return make_pair(B.first-A.first,B.second-A.second); }
    LL cross(const pii &A, const pii &B){ return 1ll * A.first * B.second - 1ll * A.second * B.first; }
    int sgn(LL x){ return x > 0 ? 1 : x < 0 ? -1 : 0; }
    void solve(){
        int n; sci(n);
        vector<pii> point(n);
        for(auto &p : point) sci(p.first), sci(p.second);
        sort(all(point),[&](pii &A, pii &B){ return A.first==B.first?A.second<B.second:A.first<B.first; });
        sort(point.begin()+1,point.end(),[&](pii &A, pii &B){
            return atan2(A.second-point[0].second,A.first-point[0].first) < atan2(B.second-point[0].second,B.first-point[0].first);
        });
        static pii stk[MAXN];
        static int top;
        top = 0;
        stk[++top] = point[0];
        for(int i = 1; i < n; i++){
            while(top>1 and sgn(cross(V(stk[top-1],stk[top]),V(stk[top-1],point[i])))<=0) top--;
            stk[++top] = point[i];
        }
        if(top>=3 and sgn(cross(V(stk[1],stk[top]),V(stk[1],stk[top-1])))==0) top--;
        if(top>4){
            cout << "NO" << endl;
            return;
        }
        if(top<=2){
            cout << "YES" << endl;
            return;
        }
        auto sameline = [&](const pii &A, const pii &B, const pii &C){
            return sgn(cross(V(A,B),V(A,C))) == 0; 
        };
        auto check = [&](const pii &A, const pii &B){
            vector<bool> vis(n,false);
            for(int i = 0; i < n; i++){
                if(point[i]==A or point[i]==B) vis[i] = true;
                if(sameline(A,B,point[i])) vis[i] = true;
            }
            vector<pii> vec;
            for(int i = 0; i < n; i++) if(!vis[i]) vec << point[i];
            if(vec.size()<=2) return true;
            for(int i = 2; i < (int)vec.size(); i++) if(!sameline(vec[0],vec[1],vec[i])) return false;
            return true;
        };
        for(int i = 1; i < top; i++) for(int j = i + 1; j <= top; j++) if(check(stk[i],stk[j])){
            cout << "YES" << endl;
            return;
        }
        cout << "NO" << endl;
    }
    int main(){
        #ifndef ONLINE_JUDGE
        freopen("Local.in","r",stdin);
        freopen("ans.out","w",stdout);
        #endif
        solve();
        return 0;
    }
    

    E.Tufurama 

    问题等价于:对于每个(i),我们需要知道([i+1,a_i])之间有多少数大于等于(i)即可

    由于(a_i)超过(n)没什么用,所以可以先把(a_i)(n)(min),然后用主席树搞一下就好了

    view code
    #pragma GCC optimize("O3")
    #pragma GCC optimize("Ofast,no-stack-protector")
    #include<bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define endl "
    "
    #define LL long long int
    #define vi vector<int>
    #define vl vector<LL>
    #define all(V) V.begin(),V.end()
    #define sci(x) scanf("%d",&x)
    #define scl(x) scanf("%lld",&x)
    #define scs(s) scanf("%s",s)
    #define pii pair<int,int>
    #define pll pair<LL,LL>
    #ifndef ONLINE_JUDGE
    #define cout cerr
    #endif
    #define cmax(a,b) ((a) = (a) > (b) ? (a) : (b))
    #define cmin(a,b) ((a) = (a) < (b) ? (a) : (b))
    #define debug(x)  cerr << #x << " = " << x << endl
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    template <typename T> vector<T>& operator << (vector<T> &__container, T x){ __container.push_back(x); return __container; }
    template <typename T> ostream& operator << (ostream &out, vector<T> &__container){ for(T _ : __container) out << _ << ' '; return out; }
    const int MAXN = 2e5+7;
    struct SegmentTree{
        int root[MAXN], sum[MAXN<<5], ls[MAXN<<5], rs[MAXN<<5], tot;
        void modify(int &rt, int pre, int pos, int x, int l, int r){
            rt = ++tot;
            sum[rt] = sum[pre] + x; ls[rt] = ls[pre]; rs[rt] = rs[pre];
            if(l+1==r) return;
            int mid = (l + r) >> 1;
            if(pos<mid) modify(ls[rt],ls[pre],pos,x,l,mid);
            else modify(rs[rt],rs[pre],pos,x,mid,r);
        }
        int qsum(int Lrt, int Rrt, int L, int R, int l, int r){
            if(L>=r or l>=R) return 0;
            if(L<=l and r<=R) return sum[Rrt] - sum[Lrt];
            int mid = (l + r) >> 1;
            return qsum(ls[Lrt],ls[Rrt],L,R,l,mid) + qsum(rs[Lrt],rs[Rrt],L,R,mid,r);
        }
    }ST;
    void solve(){
        int n; sci(n);
        vi A(n);
        for(int &x : A) sci(x), cmin(x,n);
        LL ret = 0;
        for(int i = n; i; i--){
            int x = A[i-1];
            if(x>i) ret += ST.qsum(ST.root[x+1],ST.root[i+1],i,n+1,1,n+1);
            ST.modify(ST.root[i],ST.root[i+1],x,1,1,n+1);
        }
        cout << ret << endl;
    }
    int main(){
        #ifndef ONLINE_JUDGE
        freopen("Local.in","r",stdin);
        freopen("ans.out","w",stdout);
        #endif
        solve();
        return 0;
    }
    

    F. k-substrings

    直接二分是不行的,没有单调性

    考虑枚举前后缀的中点(i),然后找以(i)(n-i+1)为中点的最长相同串,可以发现这个长度是可以二分的,找到最长的相同串,这个用哈希就好了

    view code
    #pragma GCC optimize("O3")
    #pragma GCC optimize("Ofast,no-stack-protector")
    #include<bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define endl "
    "
    #define LL long long int
    #define vi vector<int>
    #define vl vector<LL>
    #define all(V) V.begin(),V.end()
    #define sci(x) scanf("%d",&x)
    #define scl(x) scanf("%lld",&x)
    #define scs(s) scanf("%s",s)
    #define pii pair<int,int>
    #define pll pair<LL,LL>
    #ifndef ONLINE_JUDGE
    #define cout cerr
    #endif
    #define cmax(a,b) ((a) = (a) > (b) ? (a) : (b))
    #define cmin(a,b) ((a) = (a) < (b) ? (a) : (b))
    #define debug(x)  cerr << #x << " = " << x << endl
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    template <typename T> vector<T>& operator << (vector<T> &__container, T x){ __container.push_back(x); return __container; }
    template <typename T> ostream& operator << (ostream &out, vector<T> &__container){ for(T _ : __container) out << _ << ' '; return out; }
    const int MAXN = 1e6+7;
    const int MOD1 = 998244353;
    const int MOD2 = 1004525809;
    const int BASE1 = 233;
    const int BASE2 = 1033;
    int n, pw1[MAXN], pw2[MAXN], ret[MAXN];
    pii hax[MAXN];
    char s[MAXN];
    pii calc(int l, int r){
        return make_pair((hax[r].first - 1ll * hax[l-1].first * pw1[r-l+1] % MOD1 + MOD1) % MOD1,
                         (hax[r].second - 1ll * hax[l-1].second * pw2[r-l+1] % MOD2 + MOD2) % MOD2);
    }
    void solve(){
        sci(n); scs(s+1);
        pw1[0] = pw2[0] = 1;
        for(int i = 1; i < MAXN; i++) pw1[i] = 1ll * pw1[i-1] * BASE1 % MOD1, pw2[i] = 1ll * pw2[i-1] * BASE2 % MOD2;
        for(int i = 1; i <= n; i++){
            hax[i].first = (1ll * hax[i-1].first * BASE1 + s[i]) % MOD1;
            hax[i].second = (1ll * hax[i-1].second * BASE2 + s[i]) % MOD2;
        }
        memset(ret,255,sizeof(ret));
        for(int i = 1; i <= (n >> 1); i++){
            int l = 1, r = i;
            while(l<=r){
                int mid = (l + r) >> 1;
                if(calc(i-mid+1,i+mid-1)==calc(n-i+1-mid+1,n-i+1+mid-1)) l = mid + 1;
                else r = mid - 1;
            }
            ret[i-r+1] = r * 2 - 1;
        }
        for(int i = 1; i <= (n + 1) / 2; i++) cout << (ret[i] = max(ret[i],ret[i-1] - 2)) << ' '; cout << endl;
    }
    int main(){
        #ifndef ONLINE_JUDGE
        freopen("Local.in","r",stdin);
        freopen("ans.out","w",stdout);
        #endif
        solve();
        return 0;
    }
    

    G. Partitions

    每个值对答案的贡献次数是相同的,那么答案就是所有数的和(sum)乘上每个数的贡献数

    第一种方法:

    通过枚举指定数所在块的大小(i),选出(i-1)个数和指定数在同一块中,然后剩下的(n-i)个数分成(k-1)个集合,答案应该是(sumcdotsum_{i=1}^{n-k+1}icdot binom{n-1}{i-1}cdot operatorname{stirling}(n-i,k-1))

    这样需要用任意模数(NTT)来算第二类斯特林数的列,比较麻烦

    第二种方法:

    对于指定的数,自身对自身的贡献为(operatorname{stirling}(n,k))而其他每个数只要和指定数在一个块内,就能有一次的贡献,考虑枚举把指定数和其他数捆绑在一起的方案数是((n-1)cdotoperatorname{stirling}(n-1,k)),这时候答案就是(sumcdot (operatorname{stirling}(n,k)+(n-1)cdot operatorname{stirling}(n-1,k)))

    view code
    #pragma GCC optimize("O3")
    #pragma GCC optimize("Ofast,no-stack-protector")
    #include<bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define endl "
    "
    #define LL long long int
    #define vi vector<int>
    #define vl vector<LL>
    #define all(V) V.begin(),V.end()
    #define sci(x) scanf("%d",&x)
    #define scl(x) scanf("%lld",&x)
    #define scs(s) scanf("%s",s)
    #define pii pair<int,int>
    #define pll pair<LL,LL>
    #ifndef ONLINE_JUDGE
    #define cout cerr
    #endif
    #define cmax(a,b) ((a) = (a) > (b) ? (a) : (b))
    #define cmin(a,b) ((a) = (a) < (b) ? (a) : (b))
    #define debug(x)  cerr << #x << " = " << x << endl
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    template <typename T> vector<T>& operator << (vector<T> &__container, T x){ __container.push_back(x); return __container; }
    template <typename T> ostream& operator << (ostream &out, vector<T> &__container){ for(T _ : __container) out << _ << ' '; return out; }
    const int MAXN = 2e5+7;
    const int MOD = 1e9+7;
    int fac[MAXN], inv[MAXN], rfac[MAXN];
    int ksm(int a, int b){
        int ret = 1;
        while(b){
            if(b&1) ret = 1ll * ret * a % MOD;
            b >>= 1;
            a = 1ll * a * a % MOD;
        }
        return ret;
    }
    int C(int n, int m){ return n < m ? 0 : 1ll * fac[n] * rfac[m] % MOD * rfac[n-m] % MOD; }
    int stirling(int n, int m){
        int ret = 0;
        for(int i = 0; i < m; i++) ret = (ret + (i&1?-1ll:1ll) * C(m,i) % MOD * ksm(m-i,n) % MOD) % MOD;
        return (1ll * ret * rfac[m] % MOD + MOD) % MOD;
    }
    void solve(){
        int n, k;
        sci(n); sci(k);
        vi A(n); for(int &x : A) sci(x);
        int tot = accumulate(all(A),0ll) % MOD;
        if(n==k) cout << tot << endl;
        else cout << 1ll * tot * (stirling(n,k) + 1ll * (n-1) * stirling(n-1,k) % MOD) % MOD << endl;
    }
    int main(){
        #ifndef ONLINE_JUDGE
        freopen("Local.in","r",stdin);
        freopen("ans.out","w",stdout);
        #endif
        fac[0] = rfac[0] = inv[1] = 1;
        for(int i = 1; i < MAXN; i++) fac[i] = 1ll * fac[i-1] * i % MOD;
        for(int i = 2; i < MAXN; i++) inv[i] = 1ll * (MOD - MOD / i) * inv[MOD%i] % MOD;
        for(int i = 1; i < MAXN; i++) rfac[i] = 1ll * rfac[i-1] * inv[i] % MOD;
        solve();
        return 0;
    }
    
  • 相关阅读:
    ARP 协议
    3GPP 5G UPF
    OpenStack v.s. Kubernetes
    C#- FTP递归下载文件
    C#- WinForm获取 当前执行程序路径的几种方法
    C#- 布署WinForm程序
    Delphi- 连接MySQL数据库BDE
    Delphi- 内置数据库的使用例子BDE
    CSS- 兼容样式记录
    Delphi- DLL操作
  • 原文地址:https://www.cnblogs.com/kikokiko/p/13623770.html
Copyright © 2011-2022 走看看