18.9.25 考试总结

 

这道题就是一道$log$方 枚举乘以$b$的次数 那么加上$a$的次数穿插其中

那么剩下的数可以被表示为 $a * b ^ k1 +a * b ^ k2 + a * b ^ k3 + ... $

同样的 剩下的树可以被表示成$b$进制的数 这个是同理的 所以就从枚举的次数开始往下能减得就减掉就可以了

代码

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 50;
ll p[N],a,b,S,T;
int tot = 0;

ll check(int t) {
    
    ll res = T,ans = t; res -= S * p[t];
    if(res < 0) return -1;
    for(int i = t;i >= 0;i --) {
        if(res - a * p[i] >= 0) {
            ll s = res / (a * p[i]);
            ans += s; res -= s * a * p[i];
        }
        if(! res) return ans;
    }
    if(res != 0) return -1;
}

void Solve( ) {
    
    scanf("%lld%lld%lld%lld",& S,& T,& a,& b);
    p[0] = 1;
    for(int i = 1;i < N;i ++) {
        p[i] = p[i - 1] * b;
        if(p[i] >= T) {
            if(p[i] == T) { tot = i; break;}
            else if(p[i] > T) { tot = i - 1; break; }
            if(p[i] > 1e9 + 1) { tot = i - 1; break;}
        }
    }
    ll ans = -1;
    for(int i = 0;i <= tot;i ++) {
        ll tim = check(i);
        if(ans == -1) ans = tim;
        else {
            if(tim == -1) continue;
            else ans = min(ans, tim);
        }
    }
    printf("%lld\n",ans);
}

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

 

这道题是原题啊 之前还写过博客的我 就不说了 高中线性规划题目 

代码

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

const int N = 1e5 + 5;
int n,m,a[N],b[N];

void Init( ) {
    
    scanf("%d%d",& n,& m);
    for(int i = 1;i <= m;i ++) scanf("%d%d",& a[i],& b[i]);
}

bool check(int t) {
    
    int ma1 = -oo,mi1 = oo;
    int ma2 = -oo,mi2 = oo;
    for(int i = 1;i <= m;i ++)
        if(abs(a[i] - b[i]) > t) {
            ma1 = max(a[i] + b[i] - t, ma1); mi1 = min(a[i] + b[i] + t, mi1);
            ma2 = max(a[i] - b[i] - t, ma2); mi2 = min(a[i] - b[i] + t, mi2);
        }
    return (ma1 <= mi1) && (ma2 <= mi2);
}

void Solve( ) {
    
    int l = 0,r = oo,ans = oo;
    while(l <= r) {
        int mid = l + r >> 1;
        if(check(mid)) ans = mid,r = mid - 1;
        else l = mid + 1;
    }
    printf("%d\n",ans);
}

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

 

这道题是一道图论题 

至于为什么是$n - cnt$因为对于每个环内的关系 我们都可以定下一个元素 使得他不断的与应该放在他这个位置的值进行交换

那么这个时候应该进行$size - 1$次 那么总的就是$n - cnt$次

代码

#include <bits/stdc++.h>
using namespace std;

const int N = 4e5 + 5;
int n,a[N],b[N],x[N],y[N],head[N],nex[N],tov[N];
int tot = 0,cnt = 0,stk[N],top,dfn[N],low[N],idc;
bool vis[N];

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( ) {
    
    scanf("%d",& n);
    for(int i = 0;i < n;i ++) {
        scanf("%d",& a[i]); b[i] = a[i];
    }
    for(int i = 1;i <= 2 * n;i ++) scanf("%d%d",& x[i],& y[i]);
}

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

void tarjan(int u) {
    
    vis[u] = true; stk[++ top] = u;
    dfn[u] = low[u] = ++ idc;
    for(int i = head[u];i;i = nex[i]) {
        int v = tov[i];
        if(! dfn[v]) {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        else if(vis[v]) {
            low[u] = min(low[u], dfn[v]);
        }
    }
    if(low[u] == dfn[u]) {
        cnt ++;
        while(1) {
            int x = stk[top --];
            vis[x] = false;
            if(x == u) break;
        }
    }
}

void clear( ) {
    
    memset(head, 0, sizeof(head)); tot = 0;
    memset(dfn, 0, sizeof(dfn)); cnt = 0;
    memset(vis, 0, sizeof(vis)); top = 0;
    idc = 0;
    for(int i = 0;i < n;i ++) b[i] = a[i];
}

bool check(int mid) {
    
    clear( );
    for(int i = 1;i <= mid;i ++) 
        swap(b[x[i]], b[y[i]]);
    for(int i = 0;i < n;i ++) add(b[i], i);
    for(int i = 0;i < n;i ++) 
        if(! dfn[i]) tarjan(i);
    return n - cnt <= mid;
}

void Solve( ) {
    
    int l = 0,r = 2 * n,ans = 2 * n;
    while(l <= r) {
        int mid = l + r >> 1;
        if(check(mid)) ans = mid,r =  mid - 1;
        else l = mid + 1;
    }
    printf("%d\n",ans);
}

int main( ) {
    
    freopen("c.in","r",stdin);
    freopen("c.out","w",stdout);
    Init( );
    Solve( );
}
posted @ 2018-09-25 16:59  阿澈说他也想好好学习  阅读(120)  评论(0编辑  收藏  举报