ASC45

A

题意 要求构造集合$A,B$, 使得$A+A$与$B+B$相同

只有$n$为$2$的幂时合法, 构造可以初始化$A_0=1,B_0=2$

然后让$A_{i+2^x}=B_{i}+2^{x+1},B_{i+2^x}=A_{i}+2^{x+1}$

#include <bits/stdc++.h>
#define REP(_i,_a,_n) for(int _i=_a;_i<=_n;++_i)
#define PER(_i,_a,_n) for(int _i=_n;_i>=_a;--_i)
using namespace std;
int main() {
    freopen("analogous.in","r",stdin);
    freopen("analogous.out","w",stdout);
    int n;
    while (cin>>n,n) {
        if ((n&-n)!=n) puts("No");
        else {
            puts("Yes");
            vector<int> v[2];
            v[0].push_back(1),v[1].push_back(2);
            for (int x=2; v[0].size()!=n; x<<=1) {
                int sz = v[0].size();
                REP(i,0,sz-1) v[0].push_back(v[1][i]+x),v[1].push_back(v[0][i]+x);
            }
            for (int t:v[0]) cout<<t<<' ';puts("");
            for (int t:v[1]) cout<<t<<' ';puts("");
        }
    }
}
View Code

B

题意 $f$为分段线性函数, 求最小的区间$[L,R]$, 满足$P(L\le \xi\le R | a\le f(\xi)\le b)\ge \alpha$

预处理出所有合法区间, 然后滑动区间

#include <iostream>
#include <queue>
#include <cmath>
using namespace std;
#define db double
#define abs(x) ((x)>0?(x):(-x))
#define LL long long
#define mp make_pair
#define pb push_back
#define fi first
#define se second
const db EPS = 1e-9;
const db INF = 1e18;
const db PI = acos(-1.0);
inline double torad(double deg) { return deg / 180 * PI; }//转弧度
 
inline int dcmp(double x)
{
    if(fabs(x) < EPS) return 0;
    return x < 0 ? -1 : 1;
}
struct Point{
    db x, y;
    Point(db _x = 0, db _y = 0) : x(_x), y(_y){}
    inline void read(){
        scanf("%lf %lf", &x, &y);
    }
};
// 过两点p1, p2的直线一般方程ax+by+c=0
// (x2-x1)(y-y1) = (y2-y1)(x-x1)
inline void GetLineGeneralEquation(Point p1, Point p2, double &a, double &b, double &c)
{
    a = p2.y - p1.y;
    b = p1.x - p2.x;
    c = -a * p1.x - b * p1.y;
}
const int N = 1e5+10;
int n;
Point p[N];
double a,b,x;
pair<double,double> f[N];

int main() {
    freopen("bayes.in","r",stdin);
    freopen("bayes.out","w",stdout);
    while (scanf("%d", &n), n) {
        scanf("%lf%lf%lf", &a, &b, &x);
        for (int i=0; i<=n; ++i) {
            scanf("%lf%lf", &p[i].x, &p[i].y);
        }
        int cnt = 0;
        double tot = 0;
        for (int i=1; i<=n; ++i) {
            double u,v,w;
            GetLineGeneralEquation(p[i-1],p[i],u,v,w);
            double l = p[i-1].x, r = p[i].x;
            //ax+by+c=0
            //x=(-c-by)/a
            double l1 = (-w-v*a)/u, r1 = (-w-v*b)/u;
            if (l1>r1) swap(l1,r1);
            l = max(l, l1), r = min(r, r1);
            if (l<=r) f[++cnt] = {l,r}, tot += r-l;
        }
        tot *= x;
        int now = 1;
        double l, r, len = 0;
        double ans = 1e18;
        for (int i=1; i<=cnt; ++i) {
            if (f[i].second-f[i].first>=tot) {
                l = f[i].first, r = f[i].first+tot;
                break;
            }
            while (now<=cnt&&len<tot) {
                len += f[now].second-f[now].first;
                ++now;
            }
            if (len>=tot) {
                double ret = f[now-1].second-f[i].first-len+tot;
                if (ret<ans) ans = ret, l = f[i].first, r = f[now-1].second-len+tot;
            }
            len -= f[i].second-f[i].first;
        }
        printf("%.12lf %.12lf\n", l, r);
    }
}
View Code

C

题意 求所有长$n$, 不存在$i<j<k$使得$a_k<a_i<a_j$的$ascent\space sequences$个数

从前往后填数, 维护每种数出现的状态, 始终把当前能填的最小数当做最低位, 可以发现状态会有很多重复的, 记忆化一下就可以了

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef tuple<int,int,int,ll> state;
map<state,ll> mp;
ll solve(int d, int mx, int pre, ll s) {
    state now(d,mx,pre,s);
    if (mp.count(now)) return mp[now];
    if (!d) return 1;
    ll ans = 0;
    int mi = 0;
    for (int i=0; i<=mx; ++i) {
        ans += solve(d-1,mx-mi+(i>pre),i-mi,(s|1ll<<i)>>mi);
        if (s>>i&1) mi = i;
    }
    return mp[now]=ans;
}
int main() {
    freopen("catalian.in","r",stdin);
    freopen("catalian.out","w",stdout);
    int n, clk = 0;
    while (cin>>n,n) cout<<"Case #"<<clk<<": "<<solve(n-1,1,0,1)<<endl;
}
View Code

D

题意 要求构造一个$n$点的有向图, 点$n-1$是家, 点$n$是酒吧, 其余点出度为$2$, 初始有一个酒鬼在点$1$, 每一步酒鬼等概率走向一个点, 要求最终酒鬼回家的概率为$\frac{p}{q}$

考虑二进制即可, 比如$q=13$, 那么构造$f=\frac{f}{16}+\frac{f}{8}+\frac{1}{4}+\frac{1}{2}$, $f=\frac{12}{13}$

那么就可以用$\lceil\log_2{q}\rceil$个点构造出$\frac{q-1}{q}$, 然后再递归构造$\frac{q-2}{q-1}$, 以此类推

这样构造出$\frac{p}{q}$大约要$q\lceil\log_2{q}\rceil\le 1000$可以满足条件

#include <bits/stdc++.h>
#define REP(_i,_a,_n) for(int _i=_a;_i<=_n;++_i)
#define PER(_i,_a,_n) for(int _i=_n;_i>=_a;--_i)
using namespace std;
const int N = 1e5+10;
int tot,L[N],R[N],f[N],g[N],ID[N];
int solve(int p, int q, int s) {
    int x = 1;
    while ((1<<x)<q) ++x;
    int y = (1<<x)-q, now = tot+1;
    PER(i,0,x-1) {
        ++tot;
        L[tot] = y>>i&1?now:s;
        R[tot] = i?tot+1:1;
    }
    if (p!=q-1) return solve(p,q-1,now);
    return now;
}
void gao(int x, int y) {
    if (x==y) return;
    REP(i,1,tot) {
        if (L[i]==x) f[i] = y;
        else if (L[i]==y) f[i] = x;
        else f[i] = L[i];
        if (R[i]==x) g[i] = y;
        else if (R[i]==y) g[i] = x;
        else g[i] = R[i];
    }
    REP(i,1,tot) {
        if (i==x) L[i] = f[y], R[i] = g[y];
        else if (i==y) L[i] = f[x], R[i] = g[x];
        else L[i] = f[i], R[i] = g[i];
    }
    REP(i,1,tot) {
        if (ID[i]==x) ID[i] = y;
        else if (ID[i]==y) ID[i] = x;
    }
}
int main() {
    freopen("drunkard.in","r",stdin);
    freopen("drunkard.out","w",stdout);
    int p,q;
    while (cin>>p>>q,p||q) {
        L[1] = R[1] = L[2] = R[2] = 0;
        tot = 2;
        int x = solve(p,q,2);
        REP(i,1,tot) ID[i] = i;
        gao(1,x),gao(tot-1,ID[2]),gao(tot,ID[1]);
        printf("%d\n", tot);
        REP(i,1,tot-2) printf("%d %d\n",L[i],R[i]);
    }
}
View Code

F

题意 给定一个$n$点$m$条边的图, 保证点$1$与其他所有点相连, 要求给每条边标号, 使得标号是$[1,m]$的排列, 并且每个点邻接边标号和不相同

先将与$1$不与$1$相连的边赋任意权值, 然后排序通过与$1$相连的边调整即可

#include <bits/stdc++.h>
#define REP(_i,_a,_n) for(int _i=_a;_i<=_n;++_i)
#define PER(_i,_a,_n) for(int _i=_n;_i>=_a;--_i)
using namespace std;
typedef long long ll;
const int N = 1e6+10;
int n, m, f[N], ID[N];
pair<ll,int> val[N];
int main() {
    freopen("flights.in","r",stdin);
    freopen("flights.out","w",stdout);
    while (scanf("%d%d", &n, &m), n||m) {
        REP(i,1,n) val[i].first=0,val[i].second=i;
        int now = 1;
        REP(i,1,m) {
            int u, v;
            scanf("%d%d", &u, &v);
            if (u>v) swap(u,v);
            if (u!=1) {
                val[u].first += now;
                val[v].first += now;
                f[i] = now;
                ++now;
            }
            else ID[v] = i;
        }
        sort(val+1,val+1+n);
        REP(i,2,n) f[ID[val[i].second]]=now++;
        puts("Yes");
        REP(i,1,m) printf("%d ", f[i]);puts("");
    }
}
View Code

 

posted @ 2020-07-31 23:06  dz8gk0j  阅读(191)  评论(0编辑  收藏  举报