2017 12 10 cf 个人赛--题解 SDUT 2017 Autumn Single Contest L

来源:互联网 发布:海量数据存储算法 编辑:程序博客网 时间:2024/05/16 06:22

A:
倒着求10以下的因子

#include <iostream>#include<bits/stdc++.h>using namespace std;const int maxn = 1e5;int a[maxn],b[maxn];int  factor(int n,int a[maxn],int b[maxn],int &tot){    for(int i=9;i>=2;i--)    {        while(n%i==0)        {            a[++tot] = i;            n/=i;        }    }    if(n==1)    return 1;    else return 0;}int qiu(long long x){    int sum = 1;    while(x)    {        int y = x%10;        x/=10;        sum*=y;    }    return sum;}int main(){    int n;    while(cin>>n)    {        int tot=0;        if(n==0)        {            cout<<"10"<<endl;        }        else if(n<10)        {            cout<<n<<endl;        }        else        {                int f = factor(n,a,b,tot);                 if(!f)        {            cout<<"-1"<<endl;        }        else        {           for(int i=tot;i>=1;i--)           {            printf("%d",a[i]);           }           cout<<endl;        }        }    }    return 0;}

B:
求从s到e所用最少的钱,有三种情况的票按距离从远到近分类
输入n-1个数表示第一站到其余n-1个站的距离

#include <iostream>#include<bits/stdc++.h>#pragma g++ xxx.cc O3using namespace std;const int maxn = 555000;char a[maxn],b[maxn];int main(){    int l1,l2,l3,c1,c2,c3,n,s,e,i,A[10000],D[10000];    scanf("%d %d %d %d %d %d",&l1,&l2,&l3,&c1,&c2,&c3);  //c1,c2,c3表示三种距离的票价  //l1,l2,l3表示三种收费情况的距离    scanf("%d",&n);    cin>>s>>e;    s--;e--;    //因为前缀和,所以--,取前一位    A[0] = 0;    for(int i=1;i<n;i++)    {        scanf("%d",&A[i]);       D[i] =1000000000;    }    if(s>e)        swap(s,e);//也有可能是返程//        cout<<s<<" "<<e<<endl<<endl;//        for(int i=0;i<n;i++)//            cout<<A[i]<<" ";//        cout<<endl;    for(i=s,D[s]=0;i<=e;i++)    {        n = upper_bound(&A[i],&A[e]+1,A[i]+l1)-A-1;     //   cout<<n<<" ";        D[n] = min(D[n],D[i]+c1);//更新从当前站能走到的最远的站        n = upper_bound(&A[n],&A[e]+1,A[i]+l2)-A-1;        D[n] = min(D[n],D[i]+c2);      //  cout<<n<<" ";        n = upper_bound(&A[n],&A[e]+1,A[i]+l3)-A-1;        D[n] = min(D[n],D[i]+c3);//        cout<<n;//        cout<<endl;    }    cout<<D[e]<<endl;    return 0;}

C:
参考博客
考虑K=L+1的情况,这种情况下先手无论拿多少个石子(1..L),都能剩下不超过L个石子让后手直接全部拿完。
如果我们构造一轮又一轮的这样的步骤,即k是L+1的倍数,那么每当先手取了s个石子,后手都能取L+1−s个石子,使得剩下的石子又变成L+1的倍数的情况,直到最后只剩L+1个石子,后手胜。
那么问题就变成了找到K的最小的大于2的因数,减一就是L了。

#include <iostream>#include <cmath>using namespace std;int main(){    int K,i,L;    while (cin>>K){        for (i=3;i<=(int)sqrt(K);i++){            if (K%i==0) break;        }        cout<<"i "<<i<<endl;        if (K%i==0) L=i-1;        else if (K%2==0&&K>4) L=K/2-1;        //因为去掉了因子2,所以找倍数时加上被开方漏掉的2的倍数的情况        //首先输出K%i是排除了因子2的倍数如4,8的情况,然后再特判        else L=K-1;        cout<<L<<endl;    }    return 0;}
#include <iostream>#include <bits/stdc++.h>using namespace std;int main(){#ifndef ONLINE_JUDGE  freopen("input.txt","r",stdin);  freopen("output.txt","w",stdout);#endif    int k;    scanf("%d",&k);    for(int i=3;i<=k;i++) if(k%i==0) {        printf("%d",i-1);        return 0;    }    printf("0\n");    return 0;}

D:
根据题意二分查找即可,(待+二分答案的做法)

#include <iostream>#include<bits/stdc++.h>using namespace std;struct node{    int l,r,i;}a[300000];bool operator <(node a ,node b){    if(a.l==b.l)    return a.r>b.r;    else    return a.l<b.l;}int pan(int x,int g){    if(a[x].l<=g&&g<=a[x].r)    return 1;    else return 0;}int main(){    int n;    cin>>n;    int u,v;    for(int i=1;i<=n;i++)    {        scanf("%d%d",&u,&v);        a[i].l=u;        a[i].r =  v;        a[i].i = i;    }    int m,g;    cin>>m;    sort(a+1,a+1+n);    for(int i=1;i<=m;i++)    {        scanf("%d",&g);        int f = 0;        node uu;        uu.l = g;        uu.r = g;        int u = upper_bound(a+1,a+1+n,uu)-a-1;        //cout<<u<<" ";        for(int j=u;j>=1;j--)        {            if(a[j].l<=g&&a[j].r>=g)            {                cout<<a[j].i<<endl;                f = 1;                break;            }        }        if(!f)printf("-1\n");    }    return 0;}

E:
tle 版
还有一个wa版利用取模暴力,不知道为什么为何一直wa

#include <iostream>#include <bits/stdc++.h>using namespace std;char s[500001],s1[250001];int main(){    int n,i;    scanf("%d",&n);    scanf("%s",s);    scanf("%s",s1);    if(strcmp(s,s1)==0)    {        printf("0");    }    else    {        for( i=0;i<n;i++)        {            if(strcmp(s+i,s1)==0)            {                printf("%d",n-i);                break;            }            s[n+i] = s[i];            s[n+i+1]='\0';        }        if(n==i)        {            printf("-1");        }    }    return 0;}

裸kmp板

#include <bits/stdc++.h>using namespace std;const int maxn = 600000;char s1[maxn],s2[maxn];int Next[maxn],l1,l2;void getnext(){    int i =0 ,j = -1;    Next[0] = -1;    while(i<l2)    {        if(s2[i]==s2[j]||j==-1)        {            i++,j++;            if(s2[i]!=s2[j])            {                Next[i] = j;            }            else Next[i] = Next[j];        }        else j = Next[j];    }}int kmp(){    int i=0,j = 0;    while(i<l1&&j<l2)    {        if(j==-1||s1[i]==s2[j])        {            i++,j++;        }        else j = Next[j];    }    if(j>=l2)return i-l2+1;    else return -1;}int main(){    int n,m;    while(cin>>n)    {        scanf("%s%s",s1,s2);        l1 = strlen(s1);        l2 = strlen(s2);        l1 = n*2;        for(int i=0;i<n;i++)        {            s1[i+n] = s1[i];        }        s1[l1] = 0;        getnext();        int o = kmp();        if(o==-1)        cout<<o<<endl;        else            cout<<(n-o+1)%n<<endl;    }    return 0;}

G:拓扑排序,一开始看错了,要验证的是上边的边不是下边的序列

#include <iostream>#include<bits/stdc++.h>using namespace std;const int maxn = 255000;int in[3000]= {0};struct node{    int x,y;} o[3100000];int tu[2000][2000]= {0},a[3000];int main(){    int n,m,u,v;    cin>>n>>m;    for(int i=1; i<=m; i++)    {        cin>>u>>v;        o[i].x =u;        o[i].y = v;    }//    for(int i=1; i<=n; i++)//    {//        cout<<in[i]<<" ";//       // cin>>a[i];//    }    int y;    for(int i=1; i<=n; i++)    {        cin>>y;        a[y] = i;    }    int f = 1;    for(int i=1; i<=m; i++)    {        if(a[o[i].x]>a[o[i].y])        {            f = 0;            break;        }    }    if(f)        printf("YES\n");    else        printf("NO\n");    return 0;}

F: 字符串哈希+树状数组模版

参考博客

 题意:给出一个字符串,m个操作:1,修改其中一个字符串,2,询问 [a, b] 是不是回文串。数据范围10^5。  如何快速判断字符串是不是回文串,可以用到多项式Hash。假设一个串s,那么字串s[i, j]的Hash值就是H[i, j]=s[i]+s[i+1]*x+s[i+2]*(x^2)+...+s[j]*(x^(i-j))。由于只有小写字母,因此x取27。但是H[i, j]这会很大,我们取模就可了,可以把变量类型设为unsigned long long, 那么自动溢出就相当于模2^64了。对于不同串但是Hash相同的情况,这种情况的概率是非常小的,通常可以忽略,当然我们也可以对x取多次值,求出不同情况下的Hash值。然后我们就可以用线段树或者树状数组来维护这个和了,复杂度O(nlogn)。//STATUS:C++_AC_140MS_2777KB#include <functional>#include <algorithm>#include <iostream>//#include <ext/rope>#include <fstream>#include <sstream>#include <iomanip>#include <numeric>#include <cstring>#include <cassert>#include <cstdio>#include <string>#include <vector>#include <bitset>#include <queue>#include <stack>#include <cmath>#include <ctime>#include <list>#include <set>#include <map>using namespace std;//#pragma comment(linker,"/STACK:102400000,102400000")//using namespace __gnu_cxx;//define#define pii pair<int,int>#define mem(a,b) memset(a,b,sizeof(a))#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1#define PI acos(-1.0)//typedeftypedef __int64 LL;typedef unsigned __int64 ULL;//constconst int N=100010;const int INF=0x3f3f3f3f;const int MOD=95041567,STA=8000010;const LL LNF=1LL<<60;const double EPS=1e-8;const double OO=1e15;const int dx[4]={-1,0,1,0};const int dy[4]={0,1,0,-1};const int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};ULL bit[N],c[N][2];char s[N];int n,len;inline int lowbit(int x){    return x&(-x);}void update(int x,ULL val,int flag){    while(x<=len){        c[x][flag]+=val;        x+=lowbit(x);    }}ULL sum(int x,int flag){    ULL ret=0;    while(x){        ret+=c[x][flag];        x-=lowbit(x);    }    return ret;}int main(){ //   freopen("in.txt","r",stdin);    int i,j,w,L,R;    char op[20],ch;    bit[0]=1;    for(i=1;i<N;i++)bit[i]=bit[i-1]*27;    while(~scanf("%s",s))    {        len=strlen(s);        mem(c,0);        for(i=0;i<len;i++){            update(i+1,(s[i]-'a'+1)*bit[i],0);            update(i+1,(s[len-i-1]-'a'+1)*bit[i],1);        }        scanf("%d",&n);        while(n--){            scanf("%s",op);            if(op[0]=='p'){                scanf("%d%d",&L,&R);                ULL a=(sum(R,0)-sum(L-1,0))*bit[len-R];                ULL b=(sum(len-L+1,1)-sum(len-R,1))*bit[L-1];                if(a==b)printf("Yes\n");                else printf("No\n");            }            else {                scanf("%d %c",&w,&ch);                update(w,(ch-s[w-1])*bit[w-1],0);                update(len-w+1,(ch-s[w-1])*bit[len-w],1);                s[w-1]=ch;            }        }    }    return 0;}
原创粉丝点击