ACM-ICPC 2018 沈阳赛区网络预赛-B,F,G

学长写的

B. Call of Accepted

You and your friends are at the table, playing an old and interesting game - the Call of Cthulhu.

There is a mechanism in the game: rolling the dice. You use a notation to communicate the type of dice that needs to be rolled - the operator "\mathop{\rm d}d". "x\mathop{\rm d}yxdy" means that an yy-sided dice should be rolled xx times and the sum of the results is taken.

Formally, for any two integers x, yx,y satisfying x \geq 0x≥0 and y \geq 1y≥1 , "x\mathop{\rm d}yxdy" means the sum of xx random integers in the range of [1, y][1,y]. It's obvious that either x < 0x<0 or y < 1y<1 makes the expression x {\rm d} yx d y illegal. For example: "2\mathop{\rm d}62d6" means that rolling a 66-sided dice 22 times. At this time, the result can be at least [1, 1] = 2[1,1]=2, and at most [6, 6] = 12[6,6]=12. The results of rolling can be used extensively in many aspects of the game. For example, an "1\mathop{\rm d}1001d100" can be used to determine whether an action with a percentage probability is successful, and a "3\mathop{\rm d}6+33d6+3 * 22" can be used to calculate the total damage when being attacked by 33 monsters simultaneously. In particular, the precedence of "\mathop{\rm d}d" is above "*". Since the operator "\mathop{\rm d}d" does not satisfy the associative law, it's necessary to make sure that "\mathop{\rm d}d" is right-associative.

Now the game has reached its most exciting stage. You are facing the Great Old One - Cthulhu. Because the spirit has been greatly affected, your sanity value needs to be deducted according to the result of rolling. If the sanity value loses too much, you will fall into madness. As a player, you want to write a program for knowing the minimum and maximum loss of sanity value before rolling, in order to make a psychological preparation.

The oldest and strongest emotion of mankind is fear, and the oldest and strongest kind of fear is fear of the unknown. ----H. P. Lovecraft

Input
There are multiple sets of input, at most 3030 cases.

Each set of input contains a string of only '+', '-', '*', 'd', '(', ')' and integers without spaces, indicating the expression of this sanity loss. The length of the expression will be at most 100100.

It is guaranteed that all expressions are legal, all operators except for '(' and ')' are binary, and all intermediate results while calculating are integers in the range of [-2147483648, 2147483647][−2147483648,2147483647].

The most merciful thing in the world, I think, is the inability of the human mind to correlate all its contents. We live on a placid island of ignorance in the midst of black seas of infinity, and it was not meant that we should voyage far. ----H. P. Lovecraft

Output
For each set of data, output a line of two integers separated by spaces, indicating the minimum and maximum possible values of the sanity loss.
这里写图片描述
这里写图片描述

#include<bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define x first
#define y second
#define rep(i,a,b) for(int i=a;i<(b);++i)
#define per(i,a,b) for(int i=a-1;i>=(b);--i)
#define fuck(x) cout<<'['<<#x<<' '<<(x)<<']'
#define sub(x,y) x=((x)-(y)<0)?(x)-(y)+mod:(x)-(y)
#define clr(a,b) memset(a,b,sizeof(a))
#define eps 1e-10
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> VI;
typedef pair<int, int> PII;
typedef unsigned int ui;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
const int mod = 1e9 + 7;
const int MX = 2e6 + 5;

vector<string>pre, s;
string str;

bool isoperator(string op) {
    if(op == "+" || op == "-" || op == "*" || op == "d") return 1;
    return 0;
}
int priority(string op) {
    if(op == "#") return -1;
    if(op == "(") return 0;
    if(op == "+" || op == "-") return 1;
    if(op == "*") return 2;
    if(op == "d") return 3;
    return -1;
}

void postfix() {
    stack<string> OPTR;   //运算符栈
    stack<string> OPND;   //数据栈

    OPTR.push("#");
    rep(i, 0, pre.size()) {
        if (pre[i] == "(") OPTR.push(pre[i]);
        else if(pre[i] == ")") {
            while(OPTR.top() != "(") {
                OPND.push(OPTR.top());
                OPTR.pop();
            }
            OPTR.pop();
        } else if (isoperator(pre[i])) {
            while(!OPTR.empty() && (priority(pre[i]) < priority(OPTR.top()) || priority(pre[i]) == priority(OPTR.top()) && pre[i] != "d")) {
                OPND.push(OPTR.top());
                OPTR.pop();
            }
            OPTR.push(pre[i]);
        } else OPND.push(pre[i]);
    }

    while(OPTR.top() != "#") {
        OPND.push(OPTR.top());
        OPTR.pop();
    }
    OPTR.pop();

    //利用操作符栈逆序即可得到后缀表达式
    while(!OPND.empty()) {
        OPTR.push(OPND.top());
        OPND.pop();
    }

    s.clear();
    while(!OPTR.empty()) {
        s.push_back(OPTR.top());
        OPTR.pop();
    }
}

bool is_dig(char ch) {return ch >= '0' && ch <= '9';}
void pre_solve() {
    pre.clear();
    rep(i, 0, str.length()) {
        if(is_dig(str[i])) {
            rep(j, i, str.length()) {
                if(!is_dig(str[j])) {
                    pre.push_back(str.substr(i, j - i));
                    i = j - 1;
                    break;
                }
                if(j == str.length() - 1) {
                    pre.push_back(str.substr(i, j - i + 1));
                    i = j;
                    break;
                }
            }
        } else pre.push_back(str.substr(i, 1));
    }
}
ll str_to_int(string st) {
    ll ret = 0;
    rep(i, 0, st.length()) ret = ret * 10 + st[i] - '0';
    return ret;
}

struct node {
    ll l, r;
    node(ll l = 0, ll r = 0): l(l), r(r) {}
    node(string st) {l = r = str_to_int(st);}
    node operator-(const node& _A)const {
        return node(l - _A.r, r - _A.l);
    }
    node operator+(const node& _A)const {
        return node(l + _A.l, r + _A.r);
    }
    node operator*(const node& _A)const {
        node ret;
        ll a = l * _A.l;
        ll b = l * _A.r;
        ll c = r * _A.l;
        ll d = r * _A.r;
        ret.l = min(min(a, b), min(c, d));
        ret.r = max(max(a, b), max(c, d));
        return ret;
    }
    node operator/(const node& _A)const {
        node ret;
        ll l1 = max(l, 0ll), r1 = r;
        ret.l = l1, ret.r = r1 * _A.r;
        return ret;
    }
};

int main() {
#ifdef local
    freopen("in.txt", "r", stdin);
#endif // local
    while(cin >> str) {
        pre_solve();
        postfix();
        stack<node>stk;
        node a, b;
        rep(i, 0, s.size()) if(isoperator(s[i])) {
            b = stk.top(); stk.pop();
            a = stk.top(); stk.pop();
//            printf("[%lld %lld]\n", a.l, a.r);
//            printf("[%lld %lld]\n", b.l, b.r);
            if(s[i] == "-") a = a - b;
            if(s[i] == "+") a = a + b;
            if(s[i] == "*") a = a * b;
            if(s[i] == "d") a = a / b;
            stk.push(a);
        } else stk.push(node(s[i]));
        a = stk.top();
        printf("%lld %lld\n", a.l, a.r);
    }
    return 0;
}

F. Fantastic Graph
"Oh, There is a bipartite graph.""Make it Fantastic."

X wants to check whether a bipartite graph is a fantastic graph. He has two fantastic numbers, and he wants to let all the degrees to between the two boundaries. You can pick up several edges from the current graph and try to make the degrees of every point to between the two boundaries. If you pick one edge, the degrees of two end points will both increase by one. Can you help X to check whether it is possible to fix the graph?

Input
There are at most 3030 test cases.

For each test case,The first line contains three integers NN the number of left part graph vertices, MM the number of right part graph vertices, and KK the number of edges ( 1 \le N \le 20001≤N≤2000,0 \le M \le 20000≤M≤2000,0 \le K \le 60000≤K≤6000 ). Vertices are numbered from 11 to NN.

The second line contains two numbers L, RL,R (0 \le L \le R \le 300)(0≤L≤R≤300). The two fantastic numbers.

Then KK lines follows, each line containing two numbers UU, VV (1 \le U \le N,1 \le V \le M)(1≤U≤N,1≤V≤M). It shows that there is a directed edge from UU-th spot to VV-th spot.

Note. There may be multiple edges between two vertices.

Output
One line containing a sentence. Begin with the case number. If it is possible to pick some edges to make the graph fantastic, output "Yes" (without quote), else output "No" (without quote).
这里写图片描述
这里写图片描述

#include<bits/stdc++.h>
#define LL long long
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f
#define fi first
#define se second
using namespace std;
const int maxn = 6e3+32;
int n,m,k;
int du[2000+42];
int du2[2000+32];
int L,R;
const int MX = 4000+54;
const int MXE = 19000+43;
struct MaxFlow
{
    struct Edge
    {
        int v, w, nxt;
    } edge[MXE],edge2[MXE];
    int tot, num, s, t;
    int head[MX];
    void init()
    {
        memset(head, -1, sizeof(head));
        tot = 0;
    }
    void add(int u, int v, int w)
    {
        edge[tot].v = v;
        edge[tot].w = w;
        edge[tot].nxt = head[u];
        head[u] = tot++;

        edge[tot].v = u;
        edge[tot].w = 0;
        edge[tot].nxt = head[v];
        head[v] = tot++;
    }

    int  d[MX], vis[MX], gap[MX];
    void bfs()
    {
        memset(d, 0, sizeof(d));
        memset(gap, 0, sizeof(gap));
        memset(vis, 0, sizeof(vis));
        queue<int>q;
        q.push(t);
        vis[t] = 1;
        while (!q.empty())
        {
            int u = q.front();
            q.pop();
            for (int i = head[u]; ~i; i = edge[i].nxt)
            {
                int v = edge[i].v;
                if (!vis[v])
                {
                    d[v] = d[u] + 1;
                    gap[d[v]]++;
                    q.push(v);
                    vis[v] = 1;
                }
            }
        }
    }

    int last[MX];
    int dfs(int u, int f)
    {
        if (u == t) return f;
        int sap = 0;
        for (int i = last[u]; ~i; i = edge[i].nxt)
        {
            int v = edge[i].v;
            if (edge[i].w > 0 && d[u] == d[v] + 1)
            {
                last[u] = i;
                int tmp = dfs(v, min(f - sap, edge[i].w));
                edge[i].w -= tmp;
                edge[i ^ 1].w += tmp;
                sap += tmp;
                if (sap == f) return sap;
            }
        }
        if (d[s] >= num) return sap;
        if (!(--gap[d[u]])) d[s] = num;
        ++gap[++d[u]];
        last[u] = head[u];
        return sap;
    }

    int solve(int st, int ed, int n)
    {
        int flow = 0;
        num = n;
        s = st;
        t = ed;
        bfs();
        memcpy(last, head, sizeof(head));
        while (d[s] < num) flow += dfs(s, inf);
        return flow;
    }
} F;
int S,T;
void update(int u,int v,int L,int R)
{
    F.add(u,v,R-L);
    F.add(S, v, L);
    F.add(u, T, L);

}
pair<int,int>Q[6000+53];

int main()
{
    int ka = 1;
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        F.init();
        S = n+m+2;
        T = n+m+3;
        F.add(n+m+1, 0, INF);
        for(int i = 0;i<=max(n,m);i++){
            du[i] = du2[i] = 0;
        }
        scanf("%d%d",&L,&R);

        for(int i = 1;i<=n;i++){
            update(0,i,L,R);
        }
        for(int i = n+1;i<=n+m;i++)
        {
            update(i,n+m+1,L,R);
        }

        for(int i = 0;i<k;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            Q[i].first = u;
            Q[i].second = v;
            du[u]++;
            du2[v]++;
            F.add(u, v+n, 1);
        }
    printf("Case %d: ",ka++);
        int ret = F.solve(S, T, T + 11);
        if(ret != (n+m)*L) puts("No");
        else puts("Yes");
    }
}

G.Spare time
这里写图片描述

#include <bits/stdc++.h>
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define MP make_pair
#define lowbit(x) x&-x
#define clr(a) memset(a,0,sizeof(a))
#define _INF(a) memset(a,0x3f,sizeof(a))
#define FIN freopen("in.txt","r",stdin)
#define IOS ios::sync_with_stdio(false)
#define fuck(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>pll;
typedef pair<int, int>pii;
typedef vector<int> VI;
const int inf = 0x3f3f3f3f;
const int MX = 1e5 + 7;
const int mod = 1e9 + 7;

int n, m;
ll qpow(ll a, ll b) {
    ll res = 1;
    while (b) {
        if (b & 1) res = (res * a) % mod;
        a = (a * a) % mod;
        b >>= 1;
    }
    return res;
}

int prime[MX], pcnt;
bool is_prime[MX];
void prime_init() {
    for (int i = 0; i < MX; i++) is_prime[i] = true;
    pcnt = 0;
    for (int i = 2; i < MX; i++) {
        if (is_prime[i])
            prime[pcnt++] = i;
        for (int j = 0; j < pcnt; j++) {
            if (i * prime[j] >= MX) break;
            is_prime[i * prime[j]] = false;
            if (i % prime[j] == 0)
                break;
        }
    }
}

vector<int>pr;
void solve(int x, VI &ver) {
    for (int i = 0; i < pcnt && (ll)prime[i]*prime[i] <= x; i++) {
        if (x % prime[i] == 0) {
            ver.pb(prime[i]);
            while (x % prime[i] == 0) x /= prime[i];
        }
    }
    if (x != 1)
        ver.pb(x);
}

int main() {
    //FIN;
    prime_init();
    ll inv2 = qpow(2ll, mod - 2);
    ll inv6 = qpow(6ll, mod - 2);
    while (~scanf("%d%d", &n, &m)) {
        ll ans = ((ll)n * (n + 1) % mod * (2 * n + 1) % mod * inv6 % mod + (ll)n * (n + 1) % mod * inv2 % mod) % mod;
        pr.clear();
        solve(m, pr);
        int sz = pr.size();
        for (int i = 1; i < (1 << sz); i++) {
            ll cnt = 1;
            int num = 0;
            for (int j = 0; j < sz; j++) {
                if ((i >> j) & 1) {
                    num++;
                    cnt = cnt * pr[j];
                }
            }
            ll p = n / cnt;
            ll tmp = cnt % mod * cnt % mod * (p % mod * (p + 1) % mod * (2 * p + 1) % mod * inv6 % mod) % mod;
            ll tmp2 = cnt % mod * ((p + 1) % mod * p % mod * inv2 % mod) % mod;
            if (num % 2 == 0) ans = (ans + tmp + tmp2) % mod;
            else ans = ((ans - (tmp + tmp2)) % mod + mod) % mod;
        }
        cout << ans << endl;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Cwolf9/p/9617408.html