2018.9.3模拟赛

\(T1\)
直接考虑二分就可以了。。。
二分spfa判断,直接AC一发!

#include<bits/stdc++.h>
using namespace std;
struct edge{
    int to,nxt;
    double val;
} e[400010];
int l1,l2,r1,r2,xz,n,m,cnt = 0,head[50010],fa[50010],u[200010],v[200010],x[5010],dis[50010],vis[50010],s,t,que[200010],w[200010];
double  l = 15000,r;
inline int read (){
    int q=0,f=1;char ch = getchar();
    while(!isdigit(ch)) {
        if(ch=='-')f=-1;ch=getchar();
    }
    while(isdigit(ch)){
        q=q*10+ch-'0';ch=getchar();
    }
    return q*f;
}
inline double minn(double a,double b)
{
    if (a < b) return a; else return b; 
}
inline double maxx(double a,double b)
{
    if (a > b) return a; else return b;
}
inline void add(int a,int b,double c)
{
    e[++cnt].to = b;
    e[cnt].val = c;
    e[cnt].nxt = head[a];
    head[a] = cnt;
}
inline bool Spfa(int xx)
{
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    int ll = 0,rr = 1;
    que[1] = s;
    vis[s] = 1;
    dis[s] = 0;
    while (ll < rr)
    {
        ll ++;
        int u = que[ll];
        vis[u] = 0;
        for (int i = head[u]; i ; i = e[i].nxt)
        {
            if (e[i].val >= xx && dis[e[i].to] > dis[u] + 1)
            {
                dis[e[i].to] = dis[u] + 1;
                if (!vis[e[i].to])
                {
                    rr ++;
                    que[rr] = e[i].to;
                    vis[e[i].to] = 1;
                }
            }
        }
    }
    if (dis[t] != 0x3f3f3f3f) return 1; else return 0;
}
inline bool Spfaa(int xx)
{
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    int ll = 0,rr = 1;
    que[1] = s;
    vis[s] = 1;
    dis[s] = 0;
    while (ll < rr)
    {
        ll ++;
        int u = que[ll];
        vis[u] = 0;
        for (int i = head[u]; i ; i = e[i].nxt)
        {
            if (e[i].val  <= xx && e[i].val >= l1 * 1.000 && dis[e[i].to] > dis[u] + 1)
            {
                dis[e[i].to] = dis[u] + 1;
                if (!vis[e[i].to])
                {
                    rr ++;
                    que[rr] = e[i].to;
                    vis[e[i].to] = 1;
                }
            }
        }
    }
    if (dis[t] != 0x3f3f3f3f) return 1; else return 0;
}
int main()
{
    freopen("trip.in","r",stdin);
    freopen("trip.out","w",stdout);
    n = read();
    m = read();
    for (int i = 1; i <= m; i ++)
    {
        u[i] = read();
        v[i] = read();
        w[i] = read();
    }
    for (int i = 1; i <= n; i ++)
    {
        int num = read();
        for (int j = 1; j <= num; j ++)
        {
            fa[read()] = i;
        }
    }
    for (int i = 1; i <= n; i ++)
    {
        x[i] = read();
    }
    s = read();
    t = read();
    for (int i = 1; i <= m; i ++)
    {
        double ww = w[i] * (x[fa[u[i]]] + x[fa[v[i]]]) * 1.000 / 200;
        add(u[i],v[i],ww);
        add(v[i],u[i],ww);
        l = minn(l,ww);
        r = maxx(r,ww);
    }
    l1 = l;
    l2 = l;
    r1 = r;
    r2 = r;
    if (r1 - r != 0) 
    {
        r1 ++;
        r2 ++;  
    } 
    //cout<<l1<<' '<<r1<<endl;
    while (l1 < r1)
    {
        int mid = (l1 + r1) >> 1;
        if (Spfa(mid)) l1 = mid + 1; else r1 = mid;
        //cout<<l1<<' '<<r1<<endl;
    }
    while (!Spfa(l1)) l1 --;
    l2 = l1;
    while (l2 < r2)
    {
        int mid = (l2 + r2) >> 1;
        if (Spfaa(mid)) r2 = mid; else  l2 = mid + 1;
    }
    while (!Spfaa(l2)) l2 ++;
    printf("%d %d",l1,l2);
    return 0;
}

\(T2\)
推式子题。。。其实如果不想推的话可以直接高精。。。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 4010;
const int maxm = 100010;
inline int read (){
    int q=0,f=1;char ch = getchar();
    while(!isdigit(ch)) {
        if(ch=='-')f=-1;ch=getchar();
    }
    while(isdigit(ch)){
        q=q*10+ch-'0';ch=getchar();
    }
    return q*f;
}
const int lim = 100000000;
char s[100010];
int n,k;
int kth[maxm];
ll a[maxn];
bool vis[maxm];
int cnt = 1;
int main () {
    freopen("array.in","r",stdin);
    freopen("array.out","w",stdout);
    n = read();scanf("%s",s);
    int l = 4000;
    int len = strlen(s);
    for(int i = len - 1;i >= 0; --i) {
        a[l] += (s[i] - '0') * cnt;
        cnt = (cnt<<3) + (cnt << 1);
        if(cnt == lim) l--,cnt = 1;
    }
    int tmp;
    for(tmp = 4000;a[tmp] == 0;a[tmp] = lim - 1,tmp--);
    --a[tmp];
    for(int i = 1;i <= n; ++i) {
        for(int j = l;j < 4000; ++j) {
            ll x = a[j] / i;
            a[j + 1] += lim*(a[j] - x * i);
            a[j] = x;
        }
        kth[n - i + 1] = a[4000] % i + 1;
        a[4000]/=i;
        while(a[l] == 0)  ++l;
    }
    int mx = max(0,n - 6100);
    for(int i = 1;i <= mx; ++i) {
        printf("%d ",i);
    }
    for(int i = mx + 1;i <= n; ++i) {
        int j,tot;
        for(j = mx + 1,tot = 0;tot < kth[i]; ++j) {
            if(!vis[j]) ++tot;
        }
        vis[--j] = 1;
        printf("%d ",j);
    }
    return 0;
} 

\(T3\)

照样推式子,然后枚举约数就可以了。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll a[100];
ll p[100];
ll n;
ll d[3000010];
ll cnt;
ll N;
inline ll read (){
    ll q=0,f=1;char ch = getchar();
    while(!isdigit(ch)) {
        if(ch=='-')f=-1;ch=getchar();
    }
    while(isdigit(ch)){
        q=q*10+ch-'0';ch=getchar();
    }
    return q*f;
}
inline void dfs(ll now,ll x) {
    if(now > cnt) {
        if(x < N && !(N - x & 1) && ( N - x >> 1) % x == 0) d[++d[0]] = N - x;
        return;
    }
    ll T = 1;
    for(int i = 0;i <= p[now]; ++i) {
        dfs(now + 1,x * T);
        T *= a[now];
    }
}
int main () {
    freopen("math.in","r",stdin);
    freopen("math.out","w",stdout);
    n = read();
    N = n;
    if(n == 1) {
        return puts("0");
    }
    for(ll i = 2;i * i <= n; ++i) {
        if(!(n % i)) {
            n /= i;a[++cnt] = i;
            p[cnt] = 1;
            while(!(n % i)) n /= i,++p[cnt];
        }
    }
    if(n > 1) {
        a[++cnt] = n;
        p[cnt] = 1;
    }
    dfs(1,1);
    sort(d+1,d+d[0] + 1);
    printf("%d ",d[0]);
    for(int i = 1;i <= d[0]; ++i) {
        printf("%d ",d[i]);
    }
    return 0;
}

转载于:https://www.cnblogs.com/akoasm/p/9577928.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值