BOJ 2014新生暑假个人排位赛07 整合

来源:互联网 发布:单片机输出电压不恒定 编辑:程序博客网 时间:2024/05/24 05:29

A. 暑假作业题


大模拟, 字符串读入时要注意前导0


#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cctype>#include <cmath>#include <vector>#include <queue>#include <stack>#include <map>#include <set>#include <algorithm>#include <climits> #define MAXN 100005#define eps 1e-5#define MOD 1000000009 #define test #define For(i,m,n) for(int i=(m);i<(n);i++)#define vecfor(iter,a) for(vector<int>::iterator iter=a.begin();iter!=a.end();iter++)#define rep(i,m,n) for(int i=(m);i<=(n);i++)#define LL long long /*author birdstorm*/using namespace std;const double pi=acos(-1.0); template<class T>inline bool read(T &n){    T x = 0, tmp = 1; char c = getchar();    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();    if(c == EOF) return false;    if(c == '-') c = getchar(), tmp = -1;    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();    n = x*tmp;    return true;} template <class T>inline void write(T n) {    if(n < 0) {        putchar('-');        n = -n;    }    int len = 0,data[20];    while(n) {        data[len++] = n%10;        n /= 10;    }    if(!len) data[len++] = 0;    while(len--) putchar(data[len]+48);} int main(){    int t;    LL a;    char c[20];    read(t);    while(t--){        scanf("%s",c);        int cnt=strlen(c);        bool flag1w=false, flag1e=false;        bool flagb=false, flagq=false, f3=true;        if(cnt==1&&c[0]=='0') printf("0");        for(int i=0; i<cnt; i++){            int p=cnt-i-1;            bool flag=false;            if(c[i]-'0'){                printf("%d",c[i]-'0');                flag=true;                if(p>=4&&p<8) flag1w=true;                if(p>=13&&p<16) flag1w=true;                if(p>=8) flag1e=true;            }            else{                if(c[i+1]-'0'&&p>4&&p<8&&flag1w) printf("0");                else if(c[i+1]-'0'&&p>13&&p<16&&flag1w) printf("0");                else if(c[i+1]-'0'&&(p==1||p==5||p==9||p==13)) printf("0");                else if(c[i+1]-'0'&&(p==2||p==6||p==10||p==14)) printf("0");                else if(c[i+1]-'0'&&(p==3||p==7||p==11||p==15)) printf("0");                //continue;            }            if(p==13) flag1w=false;            if(!flag){                if(flag1w&&p==4) printf("W"),flag1w=false;                if(flag1e&&p==12) printf("W"),flag1w=false;                if(flag1e&&p==8) printf("E"),flag1e=false;                continue;            }            if(p==1||p==5||p==9||p==13) printf("S");            if(p==2||p==6||p==10||p==14) printf("B");            if(p==3||p==7||p==11||p==15) printf("Q");            if(p==4||p==12) printf("W");            if(p==8) printf("E");        }        puts("");    }    return 0;}



B. 最长数链


暴力使用dfs搜索 

正确的姿势是发现数链中的数只可能是2和3的倍数, 大大降低复杂度, 可以log(n)求出

这个姿势有点慢了= =



#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cctype>#include <cmath>#include <vector>#include <queue>#include <stack>#include <map>#include <set>#include <algorithm>#include <climits> #define MAXN 100005#define eps 1e-5#define MOD 1000000009 #define test #define For(i,m,n) for(int i=(m);i<(n);i++)#define vecfor(iter,a) for(vector<int>::iterator iter=a.begin();iter!=a.end();iter++)#define rep(i,m,n) for(int i=(m);i<=(n);i++)#define LL long long /*author birdstorm*/using namespace std;const double pi=acos(-1.0); template<class T>inline bool read(T &n){    T x = 0, tmp = 1; char c = getchar();    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();    if(c == EOF) return false;    if(c == '-') c = getchar(), tmp = -1;    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();    n = x*tmp;    return true;} template <class T>inline void write(T n) {    if(n < 0) {        putchar('-');        n = -n;    }    int len = 0,data[20];    while(n) {        data[len++] = n%10;        n /= 10;    }    if(!len) data[len++] = 0;    while(len--) putchar(data[len]+48);} int prime[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43};int sta[MAXN],stac[MAXN];int dfs(int g,int pos,int cnt){    int ans=-1;    if(g==1) return cnt;    else{        For(i,pos,13){            if(g%prime[i]==0){                int len=dfs(g/prime[i],i,cnt+1);                //if(len==-1) break;                if(ans<=len){                    ans=len;                    sta[cnt+1]=prime[i];                }            }        }    }    return ans;}int ans;int main(){    int a;    while(read(a)){        ans=0;        int t;        memset(sta,0,sizeof sta);         for(int i=a/2+1;i<=a;i++){            int len=dfs(i,0,0);            if(len>=ans){                ans=len;                For(j,0,ans+1) stac[j]=sta[j];                t=i;            }        }        //ans=dfs(t,0,0);        //For(j,0,ans+1) stac[j]=sta[j];        int g=1;        printf("1");        for(int i=ans;i>=1;i--){            printf(" %d",g*stac[i]);            g*=stac[i];            if(g==t) break;        }        puts("");    }    return 0;}



C. 三角形的传说


可以证明只有三种可能解, 判断即可



#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cctype>#include <cmath>#include <vector>#include <queue>#include <stack>#include <map>#include <set>#include <algorithm>#include <climits> #define MAXN 100005#define eps 1e-5#define MOD 1000000009 #define test #define For(i,m,n) for(int i=(m);i<(n);i++)#define vecfor(iter,a) for(vector<int>::iterator iter=a.begin();iter!=a.end();iter++)#define rep(i,m,n) for(int i=(m);i<=(n);i++)#define LL long long /*author birdstorm*/using namespace std;const double pi=acos(-1.0); template<class T>inline bool read(T &n){    T x = 0, tmp = 1; char c = getchar();    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();    if(c == EOF) return false;    if(c == '-') c = getchar(), tmp = -1;    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();    n = x*tmp;    return true;} template <class T>inline void write(T n) {    if(n < 0) {        putchar('-');        n = -n;    }    int len = 0,data[20];    while(n) {        data[len++] = n%10;        n /= 10;    }    if(!len) data[len++] = 0;    while(len--) putchar(data[len]+48);}  int main(){    int t, cs=1;    int m, q;    scanf("%d",&t);    while(t--){        read(m),read(q);        printf("Case %d: ",cs++);        int ans=10000000;        if(m%2==0){            if(m>=q*2){                ans=2*q+2*m;            }            else ans=2*q+m;        }        else{            if(2*q>m){                ans=2*q+m;            }            else ans=2*q+2*m;        }        if(q<=1) ans=3*m+2*q;        printf("%d\n",ans);    }    return 0; }



D. 帮帮小叮当



dp/图论

dp的正确性: 由于是从确定状态转移至不确定状态, 所以dp的结果正确.

图论可采用SPFA, 速度也不慢.

可是使用dij+堆优化的话似乎不能在时限内通过, 原因不明



#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cctype>#include <cmath>#include <vector>#include <queue>#include <stack>#include <map>#include <set>#include <algorithm>#include <climits> #define MAXN 100005#define eps 1e-5#define MOD 1000000007#define INF 1000000007 #define test #define For(i,m,n) for(int i=(m);i<(n);i++)#define vecfor(iter,a) for(vector<int>::iterator iter=a.begin();iter!=a.end();iter++)#define rep(i,m,n) for(int i=(m);i<=(n);i++)#define LL long long /*author birdstorm*/using namespace std;const double pi=acos(-1.0); template<class T>inline bool read(T &n){    T x = 0, tmp = 1; char c = getchar();    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();    if(c == EOF) return false;    if(c == '-') c = getchar(), tmp = -1;    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();    n = x*tmp;    return true;} template <class T>inline void write(T n) {    if(n < 0) {        putchar('-');        n = -n;    }    int len = 0,data[20];    while(n) {        data[len++] = n%10;        n /= 10;    }    if(!len) data[len++] = 0;    while(len--) putchar(data[len]+48);} int dp[MAXN], a[MAXN];int main(){    int n, m;    while(read(n)&&read(m),n||m){        For(i,0,n) read(a[i]);        int ans=INF;        dp[0]=a[0]-1;        For(i,1,n) dp[i]=min(dp[i-1]+1,i+a[i]-1);        for(int i=n-2;i>=0;i--) dp[i]=min(dp[i],dp[i+1]+1);        For(i,0,n) ans=min(ans,dp[i]+n-i+m-a[i]-1);        printf("%d\n",ans);    }    return 0;}



E. hiyot的神题



线段树维护区间gcd, 然后使用容斥原理计算答案.

考虑到1000以内的数分解素数后最多只有五个, 也可以暴力手算容斥.

比如:

LL solve(LL a, LL m){    int sz=g[a].size();    LL ret=0;    if(sz==1) ret=m-m/g[a][0];    else if(sz==2) ret=m-m/g[a][0]-m/g[a][1]+m/(g[a][0]*g[a][1]);    else if(sz==3){        LL a1=g[a][0], a2=g[a][1], a3=g[a][2];        ret=m-m/a1-m/a2-m/a3+m/(a1*a2)+m/(a1*a3)+m/(a2*a3)-m/(a1*a2*a3);    }    else if(sz==4){        LL a1=g[a][0], a2=g[a][1], a3=g[a][2], a4=g[a][3];        ret=m-m/a1-m/a2-m/a3-m/a4+m/(a1*a2)+m/(a1*a3)+m/(a1*a4)+m/(a2*a3)+m/(a2*a4)+m/(a3*a4)-m/(a1*a2*a3)-m/(a1*a2*a4)-m/(a1*a3*a4)-m/(a2*a3*a4)+m/(a1*a2*a3*a4);    }    else if(sz==5){        LL a1=g[a][0], a2=g[a][1], a3=g[a][2], a4=g[a][3], a5=g[a][4];        ret=m-m/a1-m/a2-m/a3-m/a4-m/a5+m/(a1*a2)+m/(a1*a3)+m/(a1*a4)+m/(a1*a5)+m/(a2*a3)+m/(a2*a4)+m/(a2*a5)+m/(a3*a4)+m/(a3*a5)+m/(a4*a5)-m/(a1*a2*a3)-m/(a1*a2*a4)-m/(a1*a2*a5)-m/(a1*a3*a4)-m/(a1*a3*a5)-m/(a1*a4*a5)-m/(a2*a3*a4)-m/(a2*a3*a5)-m/(a2*a4*a5)-m/(a3*a4*a5)+m/(a1*a2*a3*a4)+m/(a1*a2*a3*a5)+m/(a1*a2*a4*a5)+m/(a1*a3*a4*a5)+m/(a2*a3*a4*a5)-m/(a1*a2*a3*a4*a5);    }    return ret-1;}


这里推荐的是比较优美的dfs姿势



#include <cstdio>#include <cstring>#include <cctype>#include <cstdlib>#include <vector>#include <algorithm>#define MAXN 10005#define For(i,m,n) for(int i=(m);i<(n);i++)#define LL long long    using namespace std;LL prime[]={2,3,5,7,11,13,17,19,23,29,31};struct node{    int left, right;    LL gcd;}arr[MAXN<<4];    LL num[MAXN], c;LL gcd(LL a, LL b){    return b==0?a:gcd(b,a%b);}void build(int idx, int l, int r){    arr[idx].left = l, arr[idx].right = r;    arr[idx].gcd = 0;    if(l == r){        arr[idx].gcd = num[l];        return;    }    int mid = (l + r) >> 1;    build(idx << 1, l, mid);    build(idx << 1 | 1, mid + 1, r);    arr[idx].gcd = gcd(arr[idx << 1].gcd , arr[idx << 1 | 1].gcd);}LL ans;bool query(int idx, int l, int r){    if(arr[idx].right < l||arr[idx].left > r) return false;    if(arr[idx].left >= l&&arr[idx].right <= r){        ans=gcd(ans,arr[idx].gcd);        return true;    }    query(idx << 1, l, r);    query(idx << 1 | 1, l, r);    return true;}    void update(int idx, int val, int pos){    int l = arr[idx].left, r = arr[idx].right;    if(l == r){        arr[idx].gcd=val;        return;    }    int mid = (l + r) >> 1;    if(pos <= mid) update(idx << 1, val, pos);    else update(idx << 1 | 1, val, pos);    arr[idx].gcd = gcd(arr[idx<<1].gcd, arr[idx<<1|1].gcd);}vector<LL> g[1111], v;void init(){    for(LL i=2; i<=1000; ++i){        g[i].clear();        LL tmp=i;        For(j,0,11){            if(tmp%prime[j]==0){                while(tmp%prime[j]==0) tmp/=prime[j];                g[i].push_back(prime[j]);            }        }        if(tmp!=1) g[i].push_back(tmp);    }}    LL dfs(int pos, int sz, LL a, LL m){    LL ret=0;    For(i,pos,sz){        ret+=m/g[a][i]-dfs(i+1,sz,a,m/g[a][i]);    }    return ret;}    int main(){    int t, n, q, l, r;    LL g1, m;    init();    while(~scanf("%d",&n)){        scanf("%lld%d",&m,&q);        For(i,1,n+1) scanf("%lld",&num[i]);        build(1,1,n);        int o;        while(q--){            scanf("%d%d",&o,&l);            if(o==1){                scanf("%d",&r);                ans=num[l];                query(1,l,r);                if(ans==1) printf("-1\n");                else{                    int sz=g[ans].size();                    LL ret=m-1-dfs(0,sz,ans,m);                    printf("%lld\n",ret);                }            }            else{                scanf("%lld",&g1); num[l]=g1;                update(1,g1,l);            }        }    }    return 0;}



0 0
原创粉丝点击