18.10.31 考试总结

今天考试总算开始走入正轨了 早上强行逼着自己不去睡觉...。 把T1肝出来了... 不容易 T3是原题 最后二十分钟爆手速95分 少判了个重边

 

这道题是一道推公式的题目 因为所有的格子都是由之前的格子推过来的 所以可以忽略中间部分的格子 只考虑给出的格子

首先可以发现$(1, 1)$毫无用处 继续考虑每个格子的数向下之后会乘$b$向右乘$a$

所以将格子初始考虑成水流将贡献分开计算 最终流向$(n, n)$

每流一格自身的贡献会乘上一个系数并对这个格子产生贡献 所以考虑它有多少种产生贡献的方法 显然总的路程是知道的 

所以路程数取一下组合数即可 他路径中的贡献就是$t * a^{x} * b^{y},x$是总路程中向右走的次数 $y$是向左走的次数$t$是初始值

代码

#include <bits/stdc++.h>
#define il inline
#define rg register
using namespace std;

typedef long long ll;
const int N = 1e6 + 5;
const ll MOD = 1e9 + 7;
ll ans, fac[N], rfac[N], n, a, b;

il ll read( ) {
    
    ll t = 1, ans = 0;
    char x; x = getchar( );
    while(x < '0' || x > '9') {
        if(x == '-') t - 1;
        x = getchar( );
    }
    while(x >= '0' && x <= '9') {
        ans = ans * 10 + x - '0';
        x = getchar( );
    }
    return ans * t;
}

il ll fast_pow(ll a, ll b) {
    
    ll ans = 1;
    for(;b;b >>= 1, a = a * a % MOD)
        if(b & 1) ans = ans * a % MOD;
    return ans;
}

il void Init( ) {
    
    n = read( ), b = read( ), a = read( );
    fac[0] = 1; rfac[0] = 1;
    for(rg int i = 1;i <= 2 * n;i ++) {
        fac[i] = fac[i - 1] * i % MOD;
        rfac[i] = fast_pow(fac[i], MOD - 2);
    }
}

il ll C(ll a, ll b) {
    
    if(b > a) return 0;
    return fac[a] * rfac[a - b] % MOD * rfac[b] % MOD; 
}

il void Solve( ) {
    
    for(rg int i = 1;i <= n;i ++) {
        ll t; t = read( );
        if(i == 1) continue;
        ll x = 2, y = i;
        ll len = n - x + n - y, lenb = n - x, lena = n - y;
        ll del = t * b % MOD * C(len, lenb) % MOD * fast_pow(b, lenb) % MOD * fast_pow(a, lena) % MOD;
        ans = (ans + del) % MOD;
    }
    for(rg int i = 1;i <= n;i ++) {
        ll t; t = read( );
        if(i == 1) continue;
        ll x = i, y = 2;
        ll len = n - x + n - y, lenb = n - x, lena = n - y;
        ll del = t * a % MOD * C(len, lenb) % MOD * fast_pow(b, lenb) % MOD * fast_pow(a, lena) % MOD;
        ans = (ans + del) % MOD;
    }
    printf("%lld\n", ans);
}

int main( ) {
    
    freopen("matrix.in", "r", stdin);
    freopen("matrix.out", "w", stdout);
    Init( );
    Solve( );
}

  

这道题考试的时候觉得是贪心.. 但是这数据范围一看就不是贪心 所以就打了个暴搜

使用记忆化搜索 首先发现取数的次数满足二分性 所以考虑二分

每次搜索的时候对当前位置的数枚举它能够放$i$个$p$ 放$q$是有限制的 限制为$all - i$

因为题目保证取出数的时候不能从一个数里取 所以这个数里取出$i$个$p$至少需要在外面的数取$i$个$q$

也就是里面不能取超过$all - i$个$q$ 记忆化搜索即可 复杂度相当于填表 而且还填不满 略玄学

代码

#include <bits/stdc++.h>
#define oo 1e6
#define il inline
#define rg register
using namespace std;

const int N = 1005;
int n, p, q, a[N], sum[N], vis[51][N][N], idc, all;

il int read( ) {
    
    int t = 1, ans = 0;
    char x; x = getchar( );
    while(x < '0' || x > '9') {
        if(x == '-') t - 1;
        x = getchar( );
    }
    while(x >= '0' && x <= '9') {
        ans = ans * 10 + x - '0';
        x = getchar( );
    }
    return ans * t;
}

void Init( ) {
    
    n = read( );
    if(p < q) swap(p, q);
    for(int i = 1;i <= n;i ++) a[i] = read( );
    p = read( ), q = read( );
    for(int i = n;i >= 1;i --) sum[i] = sum[i + 1] + a[i];
}

bool dfs(int dep, int nump, int numq) {
    
    if(! nump && ! numq) return true;
    if((dep == n + 1) || sum[dep] < nump * p + numq * q) return false;
    if(vis[dep][nump][numq] == idc) return false;
    for(int i = 0;i <= min(a[dep] / p, nump);i ++)
        if(dfs(dep + 1, nump - i, max(0, numq - min((a[dep] - i * p) / q, all - i)))) return true;
    vis[dep][nump][numq] = idc;
    return false;
}

bool check(int mid) {
    
    idc ++;
    all = mid;
    return dfs(1, mid, mid);
}

void Solve( ) {
    
    int l = 0, r = sum[1] / (p + q) + 1, ans = 0;
    while(l <= r) {
        int mid = l + r >> 1;
        if(check(mid)) ans = mid, l = mid + 1;
        else r = mid - 1;
    }
    printf("%lld", 1ll * ans * (p + q));
}

int main( ) {
    
    freopen("pq.in", "r", stdin);
    freopen("pq.out", "w", stdout);
    Init( );
    Solve( );
}

 

  

对不起这是一道原题..。 最后爆手速赶出来了

多起点多重点$spfa$即可 记得判重边 我这里掉了五分

代码

#include <bits/stdc++.h>
#define il inline
#define rg register
#define oo 1e9
using namespace std;

const int N = 3 * 1e4 + 5;
const int M = 2 * 1e5 + 5;
int n, m, head[N], nex[M], tov[M], val[M], tot = 1;
int dis[N], ee[N], len[N], ans;
bool vis[N];
queue<int>Q;

il int read( ) {
    
    int t = 1, ans = 0;
    char x; x = getchar( );
    while(x < '0' || x > '9') {
        if(x == '-') t - 1;
        x = getchar( );
    }
    while(x >= '0' && x <= '9') {
        ans = ans * 10 + x - '0';
        x = getchar( );
    }
    return ans * t;
}

il void add(int u, int v, int w) {
    
    tot ++; nex[tot] = head[u];
    tov[tot] = v; val[tot] = w; head[u] = tot;
}

il void Init( ) {
    
    n = read( ), m = read( );
    for(rg int i = 1;i <= m;i ++) {
        int u, v, w1, w2; u = read( ), v = read( ), w1 = read( ), w2 = read( );
        add(u, v, w1); add(v, u, w2);
    }
}

il void spfa(int st) {
    
    memset(dis, 0x3f3f3f3f, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    memset(len, 0x3f3f3f3f, sizeof(len));
    for(rg int i = head[1];i;i = nex[i]) {
        int v = tov[i];
        len[v] = min(len[v], val[i ^ 1]);
        if(v & (1 << (st - 1))) {
            vis[v] = true; Q.push(v);
            dis[v] = min(dis[v], val[i]);
        } 
    }
    while(! Q.empty( )) {
        int u = Q.front( ); Q.pop( ); vis[u] = false;
        for(rg int i = head[u];i;i = nex[i]) {
            int v = tov[i]; if(v == 1) continue;
            if(dis[v] > dis[u] + val[i]) {
                dis[v] = dis[u] + val[i];
                if(! vis[v]) {
                    Q.push(v); vis[v] = true;
                }
            }
        }
    }
    for(int i = head[1];i;i = nex[i]) {
        int v = tov[i]; 
        if(! (v & (1 << (st - 1)))) {
            ans = min(ans, dis[v] + len[v]);
        }
    }
    memset(dis, 0x3f3f3f3f, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    for(rg int i = head[1];i;i = nex[i]) {
        int v = tov[i];
        len[v] = min(len[v], val[i ^ 1]);
        if(!(v & (1 << (st - 1)))) {
            vis[v] = true; Q.push(v);
            dis[v] = min(dis[v], val[i]);
        } 
    }
    while(! Q.empty( )) {
        int u = Q.front( ); Q.pop( ); vis[u] = false;
        for(rg int i = head[u];i;i = nex[i]) {
            int v = tov[i]; if(v == 1) continue;
            if(dis[v] > dis[u] + val[i]) {
                dis[v] = dis[u] + val[i];
                if(! vis[v]) {
                    Q.push(v); vis[v] = true;
                }
            }
        }
    }
    for(rg int i = head[1];i;i = nex[i]) {
        int v = tov[i]; 
        if(v & (1 << (st - 1))) {
            ans = min(ans, dis[v] + len[v]);
        }
    }
}

int main( ) {
    
    freopen("graph.in", "r", stdin);
    freopen("graph.out", "w", stdout);
    Init( ); ans = oo; int h = 0;
    for(int i = head[1]; i; i = nex[i]) {
        int v = tov[i];
        for(int j = 30;j >= 1;j --) {
            if(v & (1 << (j - 1))) {
                h = max(h, j); break;
            }
        }
    }
    for(int i = 1;i <= h;i ++) {
        spfa(i);
    }
    printf("%d\n", ans);
}
posted @ 2018-10-31 15:44  阿澈说他也想好好学习  阅读(175)  评论(0编辑  收藏  举报