zoukankan      html  css  js  c++  java
  • Gym

    -------------------题目难度较难,但挺有营养的。慢慢补。

    A .ASCII Addition

    pro:用一定的形式表示1到9,让你计算加法。

    sol:模拟。 

    solved by fzl;

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=2000010;
    typedef long long ll;
    string s[11] =
    {
        "xxxxxx...xx...xx...xx...xx...xxxxxx",
        "....x....x....x....x....x....x....x",
        "xxxxx....x....xxxxxxx....x....xxxxx",
        "xxxxx....x....xxxxxx....x....xxxxxx",
        "x...xx...xx...xxxxxx....x....x....x",
        "xxxxxx....x....xxxxx....x....xxxxxx",
        "xxxxxx....x....xxxxxx...xx...xxxxxx",
        "xxxxx....x....x....x....x....x....x",
        "xxxxxx...xx...xxxxxxx...xx...xxxxxx",
        "xxxxxx...xx...xxxxxx....x....xxxxxx",
        ".......x....x..xxxxx..x....x......."
    };
    char Map[10][1000];
    int judge(int x)
    {
        string tmp;
        for(int i = 0; i < 7; i++)
            for(int j = x; j < x + 5; j++)tmp += Map[i][j];
        for(int i = 0; i <= 10; i++)if(s[i] == tmp)return i;
    }
    int main()
    {
        for(int i = 0; i < 7; i++)cin >> Map[i];
        int n = strlen(Map[0]);
        ll cnt = 0, a;
        for(int i = 0; i < n; i += 6)
        {
            int tmp = judge(i);
            if(tmp == 10){a = cnt;cnt = 0;continue;}
            cnt = cnt * 10 + tmp;
        }
        a = a + cnt;
        stringstream ss;string tmp;
        ss << a;
        ss >> tmp;
        for(int i = 0; i < 7; i++)for(int j = 0; j < tmp.size(); j++)
        {
            for(int k = 5 * i; k < 5 * i + 5; k++)cout<<s[tmp[j] - '0'][k];
            if(j == tmp.size() - 1)cout<<endl;
            else cout<<".";
        }
        return 0;
    }
    View Code

    B .Book Borders

    pro:给定文本,假设每行最多放L个字母时,统计第一行的信息。

    sol:模拟+二分即可。

    solve by pb。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    string s[500010];
    int a,b,cnt,ans,n,sum[500010]; 
    template<class T>
    inline void read(T&a){
        char c=getchar();
        for(a=0;(c<'0'||c>'9')&&c!='-';c=getchar());
        bool f=0;if(c=='-')f=1,c=getchar();
        for(;c>='0'&&c<='9';c=getchar())a=a*10+c-'0';
        if(f)a=-a;
    }
    int main(){
        ios::sync_with_stdio(false);
        while(cin.peek()!='
    ')cin>>s[++n],sum[n]=sum[n-1]+s[n].size();
        cin>>a>>b;
        for(int i=a;i<=b;i++){
            int las=0,mid,l,r,now,hang=0;
            ans=0;
            while(las<n){
                l=las+1,r=n;
                while(l<=r){
                    mid=(l+r)>>1;
                    if(sum[mid]-sum[las]+mid-las-1<=i)now=mid,l=mid+1;
                    else r=mid-1;
                }
                ans+=s[las+1].size();
                las=now;hang++;
            }
            printf("%d
    ",ans+hang-1);
        }
        return 0;
    }
    View Code

    D .Digit Division

    pro:给定一个数字串,让你切割,使得切割后的每一部分都是M的倍数。

    sol:保存前面切割的方案数,dp即可。 没mod 1e9+7,wa了一发。

    solve by fcy。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=2000010;
    const int Mod=1e9+7;;
    ll ans,mp; char c[maxn];
    int main()
    {
        mp=1;
        int N,M,x=0;
        scanf("%d%d%s",&N,&M,c+1);
        rep(i,1,N){
            x=x*10+c[i]-'0'; x%=M;
            if(x==0) ans=mp,(mp+=mp)%=Mod;
            else ans=0;
        }
        printf("%lld
    ",ans%Mod);
        return 0;
    }
    View Code

    F.Frightful Formula

    pro:给定N*N矩阵,给出第一行第一列的初始值 f[i][1]和f[1][i],其他位置的满足f[i][j]=a*f[i][j-1]+b*f[i-1][j]+c;  求f[N][N];

    sol:如果没有c,此题直接组合数可以做,但是有c,可能要fft或者其他多项式的算法。 比较麻烦。

    我们可以想办法把c去掉,不过数学渣fcy好像不会,只能参考别人的。 待定系数法很好的解决了这个问题。

    参考:https://blog.csdn.net/liufengwei1/article/details/78271574

    H .Hovering Hornet

    pro:三维平面里,给定一个5*5*5的立方体,内部含有一个1*1*1的骰子,现在有一只蜜蜂,问它看到的点数和的期望。

    sol:由于二者都是处于水平位置,所以看到上面的点的概率是一定的。 而周围4个点的概率取决于底面的面积,直接用半平面交即可。

    updated by fcy。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=10010;
    const double eps=1e-8;
    struct point{
        double x,y;
        point(){}
        point(double xx,double yy):x(xx),y(yy){}
    };
    struct line{
        point a;//起点
        point p;//起点到终点的向量
        line(){}
        line(point aa,point pp):a(aa),p(pp){}
        double angle;
    };
    double dot(point a,point b){ return a.x*b.x+a.y*b.y;}
    double det(point a,point b){ return a.x*b.y-a.y*b.x;}
    point operator *(point A,double p){ return point(A.x*p,A.y*p);}
    point operator +(point A,point B){return point(A.x+B.x,A.y+B.y);}
    point operator -(point A,point B){return point(A.x-B.x,A.y-B.y);}
    double getangle(point a){ return atan2(a.y,a.x);}
    double getangle(line a){ return getangle(a.p);}
    point llintersect(line A,line B)
    {
        point C=A.a-B.a;
        double t=det(C,B.p)/det(B.p,A.p);
        return A.a+A.p*t;
    }
    point s[maxn]; line t[maxn],q[maxn]; int head,tail;
    bool cmp(line a,line b){
        double A=getangle(a),B=getangle(b);
        point t=(b.a+b.p)-a.a;
        if(fabs(A-B)<eps) return det(a.p,t)>0.0;
        return A<B;
    }
    bool onright(line P,line a,line b)
    {
        point o=llintersect(a,b);
        point Q=o-P.a;
        return det(Q,P.p)>0; //如果同一直线上不能相互看到,则>=0
    }
    point w[maxn]; int pcnt=0;
    double halfplaneintersect(int N,line p)
    {
        s[N+1]=s[1];
        rep(i,1,N) t[i].a=s[i],t[i].p=s[i+1]-s[i];
        t[++N]=p;
        sort(t+1,t+N+1,cmp);
        int tot=0;
        rep(i,1,N-1) {
            if(fabs(getangle(t[i])-getangle(t[i+1]))>eps)
              t[++tot]=t[i];
        }
        t[++tot]=t[N]; head=tail=0;
        rep(i,1,tot){
            while(tail>head+1&&onright(t[i],q[tail],q[tail-1])) tail--;
            while(tail>head+1&&onright(t[i],q[head+1],q[head+2])) head++;
            q[++tail]=t[i];
        }
        while(tail>head+1&&onright(t[head+1],q[tail],q[tail-1])) tail--;
        //while(tail>head+1&&onright(t[tail],q[head+1],q[head+2])) head++;加上了会wa6,不知道为什么
        pcnt=0; q[tail+1]=q[head+1];
        rep(i,head+1,tail)  w[++pcnt]=llintersect(q[i],q[i+1]);
        double res=0;
        rep(i,2,pcnt-1) res+=det(w[i]-w[1],w[i+1]-w[1]);
        return res/2;
    }
    void solve()
    {
        double ans=0,area=5.0*5*5-1*1*1;
        rep(i,1,4) scanf("%lf%lf",&s[i].x,&s[i].y);
        ans+=6.0*halfplaneintersect(4,line(point(-0.5,0.5),point(1,0)))*5/area;
        ans+=5.0*5*5*4/area;
        ans+=4.0*halfplaneintersect(4,line(point(-0.5,-0.5),point(0,1)))*5/area;
        ans+=3.0*halfplaneintersect(4,line(point(0.5,0.5),point(0,-1)))*5/area;
        ans+=1.0*halfplaneintersect(4,line(point(0.5,-0.5),point(-1,0)))*5/area;
        printf("%.10lf
    ",ans);
    }
    int main()
    {
        solve();
        return 0;
    }
    View Code

    I .Ice Igloos

    pro:在500*500的二维平面上,给定N个圆。Q次询问,每次给出一个线段,问多少个圆和直线有交点。 N,Q<1e5

    sol:由于平面并不大,所以我们可以暴力一点的做法。 即去找可能有交点是位置,然后看那个位置上的圆是否满足。

    solved by fcy 我的做法是,枚举x坐标,然后求出这个x到直线最近的点,然后往两边找,复杂度~500*Q*常数。(比标程暴力一丢丢)

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=2000010;
    double G[510][510];
    struct point{
        double x,y;
        point(){}
        point(double xx,double yy):x(xx),y(yy){}
    }A,B;
    double det(point a,point b) {return a.x*b.y-a.y*b.x;}
    double dot(point a,point b) {return a.x*b.x+a.y*b.y;}
    double dist(point a,point b){
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    double ptoseg(point p)
    {
        point Ap=point(p.x-A.x,p.y-A.y);
        point AB=point(B.x-A.x,B.y-A.y);
        point pB=point(B.x-p.x,B.y-p.y);
        if(dot(AB,Ap)<=0) return dist(A,p);
        if(dot(AB,pB)<=0) return dist(B,p);
        return fabs(det(Ap,AB)/dist(A,B));
    }
    int ans;
    void get1(int x,int y)
    {
        while(y>=1){
            double ty=1.0*y;
            double dis=ptoseg(point(1.0*x,ty));
            if(dis>1.0) break;
            if(G[x][y]>dis) ans++;
            y--;
        }
    }
    void get2(int x,int y)
    {
        while(y<=500){
            double ty=1.0*y;
            double dis=ptoseg(point(1.0*x,ty));
            if(dis>1.0) break;
            if(G[x][y]>dis) ans++;
            y++;
        }
    }
    int main()
    {
        int N,Q;
        scanf("%d",&N);
        rep(i,1,N){
             int x,y; double r;
             scanf("%d%d%lf",&x,&y,&r);
             G[x][y]=r;
        }
        scanf("%d",&Q);
        while(Q--){
            scanf("%lf%lf%lf%lf",&A.x,&A.y,&B.x,&B.y);
            if(A.x>B.x||(A.x==B.x&&A.y>B.y)) swap(A.x,B.x),swap(A.y,B.y); ans=0;
            if(A.x==B.x){
                 for(int i=(int)A.y;i<=(int)B.y;i++)
                    ans+=(G[(int)A.x][i]>0);
            }
            else if(A.y==B.y){
                for(int i=(int)A.x;i<=(int)B.x;i++)
                    ans+=(G[i][(int)A.y]>0);
            }
            else {
                for(int i=max((int)A.x-1,1);i<=min((int)B.x+1,500);i+=1){
                   double y=1.0*A.y;
                   if(i!=A.x) y=A.y+1.0*(B.y-A.y)/(B.x-A.x)*(i-A.x);
                   int t=(int)y;
                   get1(i,t);
                   get2(i,t+1);
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    J .Juice Junctions

    pro:给定N点M边的无向图,保证没个点的度数不超过3。 现在求所有点对的最大流。N<3e3, M<4.5e3;

    sol:开始以为是N*M的复杂度,枚举起点,然后dfs,发现由于方向不能确定,所有并不能实现。

    updated by fcy。

    由于度数<=3;所以我们枚举点对,然后去验证可能性(0,1,2,3)。

    0:不连通;    1:连通;   2: 双连通; 3:删去任意一边任然是双连通。

    0,1用并查集可以做; 2用tarjan做。 3的话,需要用点东西才行,std的做法是,枚举删去的边,然后保存所有点所在的scc,所以两个点的所有情况下scc都同,即满足,这里可以用hash做。

    #include<bits/stdc++.h>
    #define ll unsigned long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=100010;
    const int seed1=131;
    const int seed2=1331;
    int Laxt[maxn],Next[maxn],To[maxn],cnt=1;
    int q[maxn],top,dfn[maxn],low[maxn],scc[maxn],scc_cnt,times;
    int fa[maxn],ans,del,hash1[maxn],hash2[maxn];
    void add(int u,int v)
    {
        Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v;
    }
    int find(int x)
    {
        if(x==fa[x]) return x;
        return fa[x]=find(fa[x]);
    }
    void dfs(int u,int f)
    {
        q[++top]=u; dfn[u]=low[u]=++times;
        for(int i=Laxt[u];i;i=Next[i]){
            if(i==del*2||i==del*2+1||To[i]==f) continue;
            if(!dfn[To[i]]) {
                dfs(To[i],u);
                low[u]=min(low[u],low[To[i]]);
            }
            else low[u]=min(low[u],dfn[To[i]]);
        }
        if(dfn[u]==low[u]){
            scc_cnt++;
            while(1){
                int x=q[top--];
                scc[x]=scc_cnt;
                if(x==u) break;
            }
        }
    }
    int main()
    {
        int N,M,u,v;
        scanf("%d%d",&N,&M);
        rep(i,1,N) fa[i]=i;
        rep(i,1,M){
            scanf("%d%d",&u,&v);
            fa[find(u)]=find(v);
            add(u,v); add(v,u);
        }
        rep(i,1,N)
         rep(j,i+1,N)
          if(find(i)==find(j)) ans++;
    
        rep(i,1,N)
          if(!dfn[i]) dfs(i,0);
    
        rep(i,1,N)
         rep(j,i+1,N)
          if(scc[i]==scc[j]) ans++;
    
        rep(i,1,M) {
            del=i; scc_cnt=0; times=0;
            rep(j,1,N) dfn[j]=scc[j]=0;
            rep(j,1,N) if(!dfn[j]) dfs(j,0);
            rep(j,1,N){
                hash1[j]=hash1[j]*seed1+scc[j];
                hash2[j]=hash2[j]*seed2+scc[j];
            }
        }
        rep(i,1,N)
         rep(j,i+1,N) if(hash1[i]==hash1[j]&&hash2[i]==hash2[j]) ans++;
        printf("%d
    ",ans);
        return 0;
    }
    View Code

    K .Kernel Knights

    pro:给定二分图。每个点有个出度,现在让你找一种方案,选出其中一些点S,满足这些点之间没有边,而未选的点,至少有S中的点指向它,保证有解。

    sol:首先,如果一个点没有入度,必选。 我们可以用topo排序得到这些点。 对于剩下的点,由于是二分图,我们选择其中一边即可。

    solve by fzl&pb

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=2000010;
    typedef long long ll;
    int n,a[200010],du[200010];
    queue<int>que;
    bool s[200010],c[200010];
    void dfs(int x,int y){
        if(y){
            c[x]=1;
            if(!s[a[x]]&&!c[a[x]])dfs(a[x],0);
        }
        else{
            s[x]=1;
            if(!s[a[x]]&&!c[a[x]])dfs(a[x],1);
        }
    }
    int main(){
        //freopen("1.in", "r", stdin);
        //freopen("1.out", "w", stdout);
        scanf("%d",&n);
        for(int i=1;i<=2*n;i++){
            scanf("%d",a+i);
            du[a[i]]++;
        }
        for(int i=1;i<=2*n;i++)
            if(!du[i])que.push(i);
        while(!que.empty()){
            int x=que.front();que.pop();
            //cout<<x<<" "<<c[x]<<endl;
            if(c[x])continue;du[a[x]]--;
            s[x]=1;
            if(!c[a[x]])c[a[x]]=1,du[a[a[x]]]--;
            if(!s[a[a[x]]] && !c[a[a[x]]] && !du[a[a[x]]])que.push(a[a[x]]);
        }
        for(int i=1;i<=2*n;i++)
            if(!s[i]&&!c[i])dfs(i,0);
        for(int i=1;i<=2*n;i++)
            if(s[i])printf("%d ",i);
        return 0;
    }
    View Code
  • 相关阅读:
    第一张图:每天初始化交易流程图
    Django部署服务时候报错:SQLite 3.8.3 or later is required (found 3.7.17)
    LOJ2494. 「AHOI / HNOI2018」寻宝游戏
    luoguP4429 [BJOI2018]染色
    LOJ2720. 「NOI2018」你的名字
    LOJ2262. 「CTSC2017」网络
    LOJ2398. 「JOISC 2017 Day 3」自然公园
    ULR1 B. 【ULR #1】光伏元件
    CF Good Bye 2020 题解&总结 A~G
    vue 导入.md文件(markdown转HTML)
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10671298.html
Copyright © 2011-2022 走看看