zoukankan      html  css  js  c++  java
  • 2019.1.29

    60pts + 0 pts+ 15pts = 75pts (我太弱了)

    T1

    T1【问题描述】 对于给定正整数 n,m,我们称正整数 c 为好的,当且仅当存在非 负整数 x,y,使得 n*x+m*y=c。 现在给出多组数据,对于每组数据,给定 n,m,q,求[1,q]内有 多少个正整数不是好的。 【输入格式】 第一行,一个整数 T 表示数据组数。 接下来每行三个数,分别表示 n,m,q,即一组询问。

     【数据范围及约定】 对于 30%的数据,n,m,q≤100。 对于 60%的数据,n,m,q≤10^5。 对于 100%的数据,n≤10^5,m≤10^9,q≤10^18,T≤10。

    首先考虑的是dp,这个时候看下数据范围qle10^{18},很显然不行。如果用数位dp的话限制条件又过多,于是pass掉dp的思路。
    稍微思考一下公式,nx+my=c,我们令n>m,则一定有n=m*k+t;由于mle100000,则一定存在t<=100000
    这时我们用一个数组f[x]记录满足n*j%m=x里最小的值n*j。因为x的值最大为100000,所以f[x]的值最后总会循环出现。再稍加推导就可以知道:
    若一个数c是好的,那么他的倍数c*k也一定是好的。
    那么我们让ans+=(q/c)
    问题还可以进一步简化。
    我们知道一定存在至少一个f_i≠0
    这时我们保证好数c中一定有至少0个n
    那么我们就让c-f_i,此时即可保证c一定是n的倍数。剩余的量全部分配给m即可。也就是ans+=(q-f[i])/m+1

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    inline ll read() {
        ll x=0;
        int f=1;
        char ch=getchar();
        while(!isdigit(ch)) {
            if(ch=='-') f=-1;
            ch=getchar();
        }
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        return x*f;
    }
    map<ll,bool>mp;
    signed main(){
    #ifndef Open
        freopen("simple.in","r",stdin),freopen("simple.out","w",stdout);
    #endif
        ios::sync_with_stdio(false);
        int t=read();
        for(register int i=1;i<=t;i++){
            mp.erase(mp.begin(),mp.end());
            int n=read(),m=read(),q=read();
            for(register int i=0;i*n<=q;i++)
            for(register int j=0;i*n+j*m<=q;j++) mp[i*n+j*m]=true;
            int ans=0;
            for(register int k=1;k<=q;k++) if(mp[k]) ans++;
            cout<<q-ans<<endl;
        }
        return 0;
    }
    暴力(60分)
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    inline ll read() {
        ll x=0;
        int f=1;
        char ch=getchar();
        while(!isdigit(ch)) {
            if(ch=='-') f=-1;
            ch=getchar();
        }
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        return x*f;
    }
    const int N=100000+5;
    int T;
    ll n,m,q,f[N];
    signed main() {
    #ifndef Open
        freopen("simple.in","r",stdin),freopen("simple.out","w",stdout);
    #endif
        T=read();
        while(T--) {
            n=read(),m=read(),q=read();
            if(q<n and q<m) {
                printf("%lld
    ",q);
                continue;
            }
            ll minn=(n<m)?n:m,maxn=n<m?m:n;
            if(q<maxn and q>=minn) {
                printf("%lld
    ",q-q/minn);
                continue;
            }
            memset(f,-1,sizeof(f));
            ll sum=0;
            f[0]=0;
            while(1) {
                sum+=maxn;
                ll x=sum%minn;
                if(f[x]!=-1) break;
                f[x]=sum;
            }
            ll ans=0;
            ans+=(q-f[0])/minn;
            for(register int i=1; i<minn; i++) if(f[i]!=-1 and q-f[i]>=0) ans+=(q-f[i])/minn+1;
            printf("%lld
    ",q-ans);
        }
        return 0;
    }
    AC(100分)

    T2

    T2【问题描述】 给定一棵 n 个节点的树,每条边的长度为 1,同时有一个权值 w。定义一条路径的权值为路径上所有边的权值的最大公约数。现在 对于任意 i∈[1,n],求树上所有长度为 i 的简单路径中权值最大的 是多少。如果不存在长度为 i 的路径,则第 i 行输出 0。 【输入格式】 第一行,一个整数 n,表示树的大小。 接下来 n-1 行,每行三个整数 u,v,w,表示 u,v 间存在一条权值 为 w 的边。 【输出格式】 对于每种长度,输出一行,表示答案。

    【数据范围及约定】 对于 30%的数据,n≤1000。 对于额外 30%的数据,w≤100。 对于 100%的数据,n≤4*10^5,1≤u,v≤n,w≤10^6。

    树上的操作,
    嗯很好,我们要在边上做文章

    考虑一下gcd的性质,
    我们不需要什么厉害的结论

    gcd(a,b)<=min(a,b)

    显然吧

    考虑边的取值不大,可以枚举一下gcd
    假设枚举的gcd是i
    那么什么样的路径可以使答案=i
    当然是权值>i的边啦
    废话。。。光是权值大没有用啊,ta还要有i这个因子啊
    换句话说就是权值要是i的倍数
    这样我们就可以在枚举gcd的时候,
    加入相应的边,找到一条树上的最长路径,更新答案

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    inline ll read() {
        ll x=0;
        int f=1;
        char ch=getchar();
        while(!isdigit(ch)) {
            if(ch=='-') f=-1;
            ch=getchar();
        }
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        return x*f;
    }
    const int N=400005;
    struct node {
        int x,y,nxt;
    };
    node e[N],way[N<<1];
    int st[N],sta[1000010],tt=0,tot=0;
    int p[N<<1],num=0;
    int ans[N],mxlen,mx,n,link[N<<1];
    inline void Add(int u,int w,int z) {
        tt++,e[tt].x=u,e[tt].y=w,e[tt].nxt=sta[z],sta[z]=tt;
    }
    inline void add(int u,int w) {
        tot++,way[tot].x=u,way[tot].y=w,way[tot].nxt=st[u],st[u]=tot,link[tot]=u;
        tot++,way[tot].x=w,way[tot].y=u,way[tot].nxt=st[w],st[w]=tot,link[tot]=w;
    }
    inline int dfs(int now) {
        p[now]=num;
        int mxson=0;
        for(register int i=st[now]; i; i=way[i].nxt)
            if(p[way[i].y]!=num) {
                int r=dfs(way[i].y);
                mxlen=max(mxlen,r+mxson+1),mxson=max(mxson,r+1);
            }
        return mxson;
    }
    signed main() {
    #ifndef Open
        freopen("walk.in","r",stdin),freopen("walk.out","w",stdout);
    #endif
        ios::sync_with_stdio(false);
        n=read();
        for(register int i=1; i<n; i++) {
            int u=read(),w=read(),z=read();
            mx=max(mx,z),Add(u,w,z);
        }
        for(register int i=1; i<=mx; i++) {
            for(register int j=i; j<=mx; j+=i)
                for(register int k=sta[j]; k; k=e[k].nxt) add(e[k].x,e[k].y);
            mxlen=0,num++;
            for(register int k=1; k<=tot; k++) if(p[link[k]]!=num) dfs(link[k]);
            for(register int k=1; k<=tot; k++) st[link[k]]=0;
            tot=0,ans[mxlen]=i;
        }
        for(register int i=n-1; i>0; i--) ans[i]=max(ans[i],ans[i+1]);
        for(register int i=1; i<=n; i++) printf("%d
    ",ans[i]);
        return 0;
    }
    AC(100分)
    #include <stdio.h>
    #include <iostream>
    #include <algorithm>
    #include <memory.h>
    #include <string.h>
    #include <vector>
    #include <time.h>
    using namespace std;
    
    typedef long long LL;
    typedef pair<int,int> mp;
    #define pb push_back
    const int inf = 1<<30;
    const int maxn = 1000005;
    const int N = 1000000;
    
    int ehead[maxn],ecnt;
    int head[maxn],cnt;
    int stk[maxn*2],top;
    struct edge{
        int u,v,next;
    }rec[maxn],edg[maxn*2];
    void add(int u,int v) {
        edg[++ecnt]=(edge){u,v,ehead[u]};
        ehead[u]=ecnt;
        edg[++ecnt]=(edge){v,u,ehead[v]};
        ehead[v]=ecnt;
        stk[++top]=u;stk[++top]=v;
    }
    void _add(int u,int v,int w) {
        rec[++cnt]=(edge){u,v,head[w]};
        head[w]=cnt;
    }
    int n,ans[maxn],maxLen;
    int vis[maxn],idx;
    int dfs(int u) {
        int maxc=0;vis[u]=idx;
        for (int v,j=ehead[u];j;j=edg[j].next)
        if (vis[v=edg[j].v]!=idx) {
            int tmpc=dfs(v);
            maxLen=max(maxLen,maxc+tmpc+1);
            maxc=max(maxc,tmpc+1);
        }
        return maxc;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
            freopen("walk.in","r",stdin);
            freopen("walk.out","w",stdout);
        #endif
        scanf("%d",&n);
        for (int u,v,w,i=1;i<n;i++)
            scanf("%d %d %d",&u,&v,&w),_add(u,v,w);
        for (int i=1;i<=N;i++) {
            for (int j=i;j<=N;j+=i)
            for (int k=head[j];k;k=rec[k].next)
                add(rec[k].u,rec[k].v);
            maxLen=0;++idx;
            for (int v,j=1;j<=top;j++)
                if (vis[v=stk[j]]!=idx) dfs(v);
            for (int j=1;j<=top;j++)
                ehead[stk[j]]=0;
            ecnt=0;top=0;ans[maxLen]=i;
        }
        for (int i=n;i>=1;i--)
            ans[i]=max(ans[i],ans[i+1]);
        for (int i=1;i<=n;i++)
            printf("%d
    ",ans[i]);
        return 0;
    }
    标程

    T3

    T3【问题描述】 给定一个长度为 n 的格子序列 x1,x2,...,xn。每一次 Lyra 可以选 择向左跳到任意一个还没到过的位置,也可以向右跳到任意一个还 没到过的位置。如果现在 Lyra 在格子 i,她下一步跳向格子 j,那 么这次跳跃的花费为|xi-xj|。注意,跳意味着格子 i 和格子 j 中间 其他的格子都不会被这次跳跃影响。并且,Lyra 不应该跳出边界。 Lyra 的初始位置在格子 s。Lyra 将会在到访过所有格子恰好一 次之后,在某个位置停下来,这样就完成了任务。 Lyra 想知道如果她一共向左跳了 L 次,那么她要完成任务的最 小总花费是多少,并希望你输出任意一种花费最小的方案。显然如 果 Lyra 向左走了 L 次,那一定会向右走 n-L-l 次。 特殊的,如果 Lyra 没有办法完成任务,请输出一行-1。 【输入格式】 第一行,三个整数 n, L,s,分别表示序列的大小,向左走的次 数,和初始位置。 第二行,n 个数字,表示序列 xi。

    T3咱做不来(咱太弱了)

    大佬的博客

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define pi pair<int,int>
    #define fi first
    #define se second
    #define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
    #define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res=1,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    char sr[1<<21],z[20];int K=-1,Z=0;
    inline void Ot(){fwrite(sr,1,K+1,stdout),K=-1;}
    void print(R int x){
        if(K>1<<20)Ot();if(x<0)sr[++K]='-',x=-x;
        while(z[++Z]=x%10+48,x/=10);
        while(sr[++K]=z[Z],--Z);sr[++K]=' ';
    }
    const int N=5e5+5;
    int x[N],y[N],ans1[N],ans2[N],pos[N],tag[N];pi st[N];
    int n,l,s;
    int solve(int n,int l,int s,int *x,int *ans){
        int cnt=0,top=0;
        if(l<s){
            fd(i,s-1,s-l+1)ans[++cnt]=i;
            fp(i,1,s-l)ans[++cnt]=i;
            fp(i,s+1,n)ans[++cnt]=i;
            return x[n]-x[1]+x[s]-x[1];
        }
        l-=s-1;
        if(l==n-s-1){
            fd(i,s-1,1)ans[++cnt]=i;
            fd(i,n,s+1)ans[++cnt]=i;
            return ((x[n]-x[1])<<1)-(x[s+1]-x[s]);
        }
        fp(i,s+1,n-2)st[++top]=pi(x[i+1]-x[i],i+1);
        sort(st+1,st+1+top);
        fp(i,1,top)pos[st[i].se]=i;
        int sum=0,mn=0,e,j;
        fp(i,1,l)sum+=st[i].fi;
        mn=sum<<1,e=n,j=l;
        for(R int i=n-1,p=l;i>=n-l;--i){
            sum-=pos[i]<=p?st[pos[i]].fi:st[p--].fi;
            while(p&&st[p].se>=i)--p;
            if(cmin(mn,(sum<<1)+x[n]-x[i]))e=i,j=p;
        }
        memset(tag,0,sizeof(tag));
        fd(i,s-1,1)ans[++cnt]=i;
        fp(i,s+2,e-1)if(pos[i]<=j)tag[i]=true;
        fp(i,s+1,e-1)if(!tag[i+1])ans[++cnt]=i;
        else{
            int tmp=i+1;while(tag[tmp])++tmp;
            fd(j,tmp-1,i)ans[++cnt]=j;
            i=tmp-1;
        }
        fd(i,n,e)ans[++cnt]=i;
        return x[n]-x[1]+x[s]-x[1]+mn;
    }
    int main(){
    //  freopen("testdata.in","r",stdin);
        freopen("travel.in","r",stdin);
        freopen("travel.out","w",stdout);
        n=read(),l=read(),s=read();
        fp(i,1,n)x[i]=read(),y[n-i+1]=-x[i];
        if(l==0&&s!=1||l==n-1&&s!=n)return puts("-1"),0;
        int c1=solve(n,l,s,x,ans1);
        int c2=solve(n,n-1-l,n+1-s,y,ans2);
        if(c1<c2){
            print(c1),sr[K]='
    ';
            fp(i,1,n-1)print(ans1[i]);
        }else{
            print(c2),sr[K]='
    ';
            fp(i,1,n-1)print(n-ans2[i]+1);
        }
        return Ot(),0;
    }
    大佬的代码
    #include <stdio.h>
    #include <iostream>
    #include <algorithm>
    #include <memory.h>
    #include <string.h>
    #include <vector>
    using namespace std;
    
    typedef long long LL;
    typedef pair<int,int> mp;
    #define pb push_back
    const LL inf = 1ll<<50;
    const int maxn = 200005;
    
    int n,l,s,pos[maxn];
    int x[maxn],ans1[maxn];
    int y[maxn],ans2[maxn];
    mp ord[maxn];
    bool tag[maxn];
    
    LL solve(int n,int l,int s,int x[],int ans[]) {
        int cnt=0,tot=0;
        if (l<s) {
            for (int i=s-1;i>s-l;i--) ans[++cnt]=i;
            for (int i=1;i<=s-l;i++) if (i!=s) ans[++cnt]=i;
            for (int i=s+1;i<=n;i++) ans[++cnt]=i;
            return (LL)x[n]-x[1]+x[s]-x[1];
        }
        l-=s-1;
        if (l==n-s-1) {
            for (int i=s-1;i>=1;i--) ans[++cnt]=i;
            for (int i=n;i>s;i--) ans[++cnt]=i;
            return (LL)x[n]-x[1]+x[s]-x[1]+x[n]-x[s+1];
        }
        
        for (int i=s+1;i<n-1;i++) ord[++tot]=mp(x[i+1]-x[i],i+1);
        sort(ord+1,ord+tot+1);
        for (int i=1;i<=tot;i++) pos[ord[i].second]=i;
        LL minv=inf,sum=0;int e,j;
        for (int i=1;i<=l;i++) sum+=ord[i].first;
        minv=sum*2;e=n;j=l;
        
        for (int i=n-1,p=l;i>=n-l;i--) {
            if (pos[i]<=p) sum-=ord[pos[i]].first;
            else sum-=ord[p--].first;
            while (p&&ord[p].second>=i) --p;
            if (sum*2+x[n]-x[i]<minv) {
                minv=sum*2+x[n]-x[i];e=i;j=p;
            }
        }
        
        memset(tag,false,sizeof tag);
        for (int i=s-1;i>=1;i--) ans[++cnt]=i;
        for (int i=s+2;i<e;i++) if (pos[i]<=j) tag[i]=true;
        for (int i=s+1;i<e;i++)
        if (!tag[i+1]) ans[++cnt]=i;
        else {
            int tmp=i+1;while (tag[tmp]) ++tmp;
            for (int j=tmp-1;j>i;j--) ans[++cnt]=j;
            ans[++cnt]=i;i=tmp-1;
        }
        for (int i=n;i>=e;i--) ans[++cnt]=i;
        return (LL)x[n]-x[1]+x[s]-x[1]+minv;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
            freopen("travel.in","r",stdin);
            freopen("travel.out","w",stdout);
        #endif
        scanf("%d %d %d",&n,&l,&s);
        for (int i=1;i<=n;i++) scanf("%d",&x[i]);
        for (int i=1;i<=n;i++) y[i]=-x[n-i+1];
        if (s!=1&&l==0) {puts("-1");return 0;}
        if (s!=n&&l==n-1) {puts("-1");return 0;}
    
        LL cost1=solve(n,l,s,x,ans1);
        LL cost2=solve(n,n-1-l,n-s+1,y,ans2);
        if (cost1<cost2) {
            printf("%lld
    ",cost1);
            for (int j=1;j<n;j++)
                printf("%d ",ans1[j]);
        }
        else {
            printf("%lld
    ",cost2);
            for (int j=1;j<n;j++)
                printf("%d ",n-ans2[j]+1);
        }
        return 0;
    }
    标程
    不存在十全十美的文章 如同不存在彻头彻尾的绝望
  • 相关阅读:
    微信支付开发
    dz插件开发(一) 从常用的常量 变量 函数开始
    收集bootstrap的几个常用用法---tooltip提示框
    ucenter接口
    php防止表单重复提交
    支付宝接口 CI上集成
    telnet模拟post 调试的时候很好用
    __call 实现函数方法不同参数个数的重载
    微赞的分页
    结合微赞发布家和小程序流程
  • 原文地址:https://www.cnblogs.com/qf-breeze/p/10332193.html
Copyright © 2011-2022 走看看