[2019杭电多校第五场]

1004传送门
[2019杭电多校第五场]_第1张图片
[2019杭电多校第五场]_第2张图片
题意:求\(\sum_{i=1}^n\) \(\mid\)a[i] * x+b[i]\(\mid\)=C(其中1<=ai<=1000,-1000<=b[i]<=1000)的所有解,如果解有无穷个则输出-1
题解:由于a[i]>=1,所以\(\mid\)a[i] * x+b[i]\(\mid\)的值在x=-b[i]/a[i]左边时==-a[i] * x-b[i],在x=-b[i]/a[i]右边时==a[i] * x+b[i],所以可以按照零点位置将n个绝对值式子排序,将数轴以这些点为界限分成若干区间,从左到右按顺序处理即可

#include
using namespace std;
//#define debug(x) cout<<#x<<" is "<aa.a*bb.b;
}
ll gcd(ll x,ll y){
    if(y==0)return x;
    return gcd(y,x%y);
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        ll n,c;
        scanf("%lld%lld",&n,&c);
        for(int i=1;i<=n;i++)scanf("%lld%lld",&p[i].a,&p[i].b);
        sort(p+1,p+1+n,cmp);
        ll s1=0;
        ll s2=0;
        int f=1;
        int tot=0;
        for(int i=1;i<=n;i++){s1-=p[i].a;s2-=p[i].b;}
        if(s1==0&&s2==c){f=0;printf("-1\n");continue;}
        if((s1>0&&(c-s2)*(p[1].a)<=(-s1*p[1].b))||(s1<0&&(c-s2)*(p[1].a)>=(-s1*p[1].b))){
            if(c-s2==0){s1=1;}
            ans1[++tot]=s1;
            ans2[tot]=c-s2;
        }
        int j;
        for(int i=1;i<=n;i=j){
            j=i;
            while(j<=n&&p[j].a*p[i].b==p[j].b*p[i].a){s1+=2*p[j].a;s2+=2*p[j].b;j++;}
            if(s1==0&&s2==c){f=0;break;}
            if(((j==n+1)||((s1>0&&(c-s2)*(p[j].a)<=(-s1*p[j].b))||(s1<0&&(c-s2)*(p[j].a)>=(-s1*p[j].b))))&&(((s1>0&&(c-s2)*(p[i].a)>=(-s1*p[i].b))||(s1<0&&(c-s2)*(p[i].a)<=(-s1*p[i].b))))){
                if(tot){
                    if(ans2[tot]*s1==ans1[tot]*(c-s2))continue;
                }
                if(c-s2==0){s1=1;}
                ans1[++tot]=s1;
                ans2[tot]=c-s2;
            }
        }
        if(f==0)printf("-1\n");
        else{
            printf("%d",tot);
            for(int i=1;i<=tot;i++){
                if(ans2[i]==0){printf(" 0/1");}
                else{
                    int xx=gcd(ans1[i],ans2[i]);
                    int sgn=1;
                    if(ans2[i]*ans1[i]<0)sgn=-1;
                    printf(" %lld/%lld",sgn*abs(ans2[i]/xx),abs(ans1[i]/xx));
                }
            }
            printf("\n");
        }
    }
    return 0;
}

1005传送门
[2019杭电多校第五场]_第3张图片
[2019杭电多校第五场]_第4张图片
题意:求出一个1到n的n个数字的一个排列并且这个排列p[i+1]-p[i]的字典序第k小
题解:使用如下dfs直接搜索p[i+1]-p[i]的值可以比较容易地找到字典序第k小的方案,重点在于复杂度的分析(代码下方附上我的分析..如有错误望指正(>_<)..)

#include
using namespace std;
//#define debug(x) cout<<#x<<" is "<

复杂度分析:由界定条件 for(int i=1-n-sum+max(0,maxx);i<=n-sum-1+min(minn,0);i++)保证这个dfs每次搜索的是一个p[i+1]-p[i]的排列,也就是不会出现搜索到无用结点的情况,每个结点最后都通向至少一个可行解,又由于只会搜索前k小的字典序,所以只有k个叶子结点,而每个被搜索到的结点都至少会被一个叶子结点经过,并且每个叶子结点到根的距离是n,所以至多会有kn个结点,而每个结点的复杂度为n,所以总的时间复杂度为O(kn*n)

1006传送门
[2019杭电多校第五场]_第5张图片
[2019杭电多校第五场]_第6张图片
[2019杭电多校第五场]_第7张图片
题意:求以\(\sum_{i=1}^(n-1)\)F(i),其中F(i)表示以s[i]开头的字符串与s[0]开头的字符串的相同前缀的长度
题解:exkmp裸题

#include
#include
#include
#include
#include
using namespace std;
char sa[1100000],sb[1100000];
int lena,lenb;
typedef long long ll;
ll p[1100000],ex[1100000];
//p数组是用来让B串自己匹配自己的
void exkmp()
{
    p[1]=lenb;
    int x=1;
    while(sb[x]==sb[x+1]&&x+1<=lenb) x++;//因为我们p[1]是具有一定性,所以我们不能直接用,所以要先暴力求出p[2]
    p[2]=x-1;
    int k=2;
    for(int i=3;i<=lenb;i++)
    {
        int pp=k+p[k]-1,L=p[i-k+1];//pp实际上是p
        if(i+Llena)ans--;}// printf("%d ",ex[i]);
        printf("%lld\n",ans);
    }
    return 0;
}

1007传送门
[2019杭电多校第五场]_第8张图片
[2019杭电多校第五场]_第9张图片
题意:求题设要求的某种排列的方案数
题解:打表

#include
using namespace std;
#define debug(x) cout<<#x<<" is "<

打表代码

#include
using namespace std;
#define debug(x) cout<<#x<<" is "<2){f=0;break;}
            }
            if(f){
                ac++;
            }
        }while(next_permutation(a+1,a+1+tot));
        printf("%d\n",ac);
    }
    return 0;
}

转载于:https://www.cnblogs.com/MekakuCityActor/p/11317345.html

你可能感兴趣的:([2019杭电多校第五场])