第一届河北工业大学程序设计竞赛校赛

比赛链接:https://ac.nowcoder.com/acm/contest/15703#question

A.WELCOME!

思路

那些输出“输出Welcome to The First Programming Competition of Hebei University of technology!”的把我人秀麻了,好想笑(磕头了o…orz)

代码

#include
using namespace std;
int main()
{
     
    cout<<"Welcome to The First Programming Competition of Hebei University of technology!"<<endl;
    return 0;
}

B.POOLING

思路

当时想着把i~i+k-1行j列的最大值存到i行j列之后输出i行j列的数只需要比较i行j ~ j+k-1列的最大值即可

PS:反正咋都不会错随便搞。

代码

#include
using namespace std;
#define ll long long
#define pii pair
#define mod 1000000007
int a[57][57];
int b[57][57];
int main()
{
     
    int n,m,k;
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
     
            scanf("%d",&a[i][j]);
            if(i>=k)
            {
     
                for(int l=i-k+1;l<=i;l++)
                {
     
                    b[i-k+1][j]=max(b[i-k+1][j],a[l][j]);
                }
            }
        }
    for(int i=1;i<=n-k+1;i++)
    {
     
        for(int j=1;j<=m-k+1;j++)
        {
     
            for(int l=j+1;l<=j+k-1;l++)
            {
     
                b[i][j]=max(b[i][j],b[i][l]);
            }
        }
    }
    printf("%d %d\n",n-k+1,m-k+1);
    for(int i=1;i<=n-k+1;i++)
    {
     
        printf("%d",b[i][1]);
        for(int j=2;j<=m-k+1;j++)
        {
     
            printf(" %d",b[i][j]);
        }
        printf("\n");
    }
    return 0;
}

C.标枪游戏

思路

出题人给的题解是离散化加树状数组,因为当时想离散化时有(没)点(get到)怕(好)冲(方)突(法),果断say no!

活用STL嘛,vector挺好用的(cf选手特别热衷?)upper_bound二分找到第一个大于numi的数的下标,也就是标枪的正得分(还有本身的标枪别忘记+1哦),负得分即为vector的元素个数减去下标。不用担心二分是不是顺序的问题,每一次插入都是按顺序插入(vector有内置插入函数嘛,下标都找到了还怕插不进去吗)

代码

#include
using namespace std;
#define ll long long
#define pii pair
const ll mod=1e9+7;
vector<ll>v1;
int main()
{
     
    ll n;
    cin>>n;
    ll ans1=0,ans2=0;
    for(ll i=1;i<=n;i++)
    {
     
        ll p;
        scanf("%lld",&p);
        if(i%2)
        {
     
            auto it=upper_bound(v1.begin(),v1.end(),p);
            ans1+=it-v1.begin()+1;
            ans1-=v1.size()-(it-v1.begin());
            v1.insert(it,p);
        }
        else{
     
            auto it=upper_bound(v1.begin(),v1.end(),p);
            ans2+=it-v1.begin()+1;
            ans2-=v1.size()-(it-v1.begin());
            v1.insert(it,p);
        }
    }
    if(ans1>ans2)
    {
     
        cout<<"Calculus is hebei king!"<<endl;
    }
    if(ans1==ans2)
    {
     
        cout<<"hebei shuang king!"<<endl;
    }
    if(ans1<ans2)
    {
     
        cout<<"huaji is hebei king!"<<endl;
    }
    return 0;
}

D.公园游玩

思路

因为是按顺序走的所以我们只需要求出第i个景点到第i+1个景点的最短路程方案数,再求乘积就是答案。

最短路程方案数怎么求呢,我们发现不管两个点怎么给坐标(a1,b1),(a2,b2),我们都可以简化为一个从点(0,0)到(abs(a1-a2),abs(b1-b2))的问题,这样可能一小部分长的比较帅的观众已经看出来了,这就是一个简单模型:从(0,0)到(n,m)只能向下和向右左的方案数,即C(n+m,n);

套个组合数板子直接A了

代码

#include
using namespace std;
#define ll long long
#define pii pair
const ll mod=1e9+7;
struct node
{
     
    int x,y;
}a[100007];
ll fac[2000007];
ll ksm(ll x,ll p){
     
    ll res=1;
    while(p){
     
        if(p%2==1) res=res*x%mod;
        p/=2;
        x=x*x%mod;
    }
    return res;
}
ll inv(ll a) {
     
	return ksm(a,mod-2)%mod;
}
void solve() {
     
	fac[0] = 1;
	for(int i = 1;i < 2000006; i++) {
     
		fac[i] = (fac[i-1]*i)%mod;
	}
}
ll comb(ll n,ll k){
     
	if(k>n)return 0;
	if(k==1)return n;
	return (fac[n]*inv(fac[k])%mod*inv(fac[n-k])%mod);
}
int main()
{
     
    solve();
    int n,m,k;
    cin>>n>>m>>k;
    int num=0;
    a[++num].x=1;
    a[num].y=1;
    for(int i=1;i<=k;i++)
    {
     
        int x,y;
        scanf("%d%d",&x,&y);
        a[++num].x=x;
        a[num].y=y;
    }
    a[++num].x=n;
    a[num].y=m;
    ll ans=1;
    for(int i=1;i<=num-1;i++)
    {
     
        int xx=min(a[i].x,a[i+1].x),yy=min(a[i].y,a[i+1].y);
        int xx1=max(a[i].x,a[i+1].x),yy1=max(a[i].y,a[i+1].y);
        ll pp=comb(xx1-xx+yy1-yy,xx1-xx);
        ans=ans*pp%mod;
    }
    cout<<ans<<endl;
    return 0;
}

E.简单数论

思路

第一届河北工业大学程序设计竞赛校赛_第1张图片

出题人已经解释的很清晰了,再就是输出ai一定不要递归%k就输出,会少输出喜提0分,别问我怎么知道的。。。

代码

#include
using namespace std;
#define ll long long
#define pii pair
const ll mod=1e18;
ll k,m,p;
ll ksm(ll a,ll b)
{
     
	ll r=1,base=a;
	while(b!=0)
	{
     
		if(b%2)
			r=r*base%mod;
		base=base*base%mod;
		b/=2;
	}
	return r%mod;
}
void print(ll x,ll num)
{
     
	if(!num)   return;
    print(x/k,num-1);
    cout<<x%k<<' ';
}
int main()
{
     
    ll t;
    cin>>t;
    while(t--)
    {
     
        
        cin>>k>>m>>p;
        ll ans=ksm(k,m)-1;
        cout<<ans<<endl;
        if(ans<p)
        {
     
            cout<<"overflow"<<endl;
        }
        else
        {
     
            p=ans+1-p;
            print(p,m);
            cout<<endl;
        }
    }
    return 0;
}

F.回文串

思路

最少一组,最多字符串多长就多少组。字母数量为奇数即需要新开一组才能回文。

代码

#include
using namespace std;
#define ll long long
#define pii pair
#define mod 1000000007
int a[107];
int main()
{
     
    string s;
    cin>>s;
    int si=s.size();
    for(int i=0;i<si;i++)
    {
     
        a[s[i]-'a'+1]++;
    }
    int num=0,ans=0;
    for(int i=1;i<=26;i++)
    {
     
        if(a[i]%2==1)
            num++;
        ans+=a[i]/2;
    }
    printf("%d\n",max(num,1));
    return 0;
}

G.数据结构好难啊

是的好难啊,非数据结构选手我不会。先空着

H.格式整理服务器

大模拟,狗都不做!

I.面基and散步

思路

第一届河北工业大学程序设计竞赛校赛_第2张图片

PS:计算几何,狗都不做!还卡我精度!

代码

#include
using namespace std;
#define ll long long
#define pii pair
const ll mod=1e9+7;
const double eps=0.000001;
const double PI=acos(-1.0);
struct point
{
     
    double x,y;
    point(){
     }
    point(double xx,double yy){
     
        x=xx,y=yy;
    }
};
struct line {
     
    point a, b;
    line(point aa,point bb){
     
        a=aa,b=bb;
    }
};
class circle {
     //circle 圆 
	public:
		point c;
		double r;
		circle(point c = point(), double r = 0.0): c(c), r(r) {
     }
};
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);
}
point operator * (point A, double p){
     
    return point(A.x*p, A.y*p);
}
bool operator == (point A, point B){
     
    return (A.x-B.x) == 0 && (A.y-B.y) == 0;
}
int sgn(double x)
{
     
    if (fabs(x) < eps)return 0;
    else return x < 0 ? -1 : 1;
}
double cross(point p1,point p2,point p3){
     //叉积
    return (p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x);
}
double dot(point p1,point p2,point p3){
     //点积
    return (p2.x-p1.x)*(p3.x-p1.x)+(p2.y-p1.y)*(p3.y-p1.y);
}
double dis(point A, point B){
     //长度
    return sqrt((A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y));
}
//点到直线的距离 
double Dis_point_line(point p, line v)
{
     
    return fabs(cross(v.a,p , v.b )) / dis(v.a, v.b);
}
double disOfPointToLine(point p,line v){
     
	if (sgn(dot(v.a,p,v.b)) < 0||sgn(dot(v.b,p,v.a)) < 0)
        return min(dis(p, v.a), dis(p, v.b));
    return Dis_point_line(p, v);		
} 
point GetLineIntersection(line u,line v) {
     //两直线交点
    point ret = u.a;
    double t = ((u.a.x-v.a.x) * (v.a.y-v.b.y) - (u.a.y-v.a.y) * (v.a.x-v.b.x)) / ((u.a.x-u.b.x) * (v.a.y-v.b.y) - (u.a.y-u.b.y) * (v.a.x-v.b.x));
    ret.x += (u.b.x - u.a.x) * t;
    ret.y += (u.b.y - u.a.y) * t;
    return ret;
}
//两向量OA,OB夹角
double angle(point O,point A,point B){
     	
	return acos(dot(O,A,B)/(dis(O,A)*dis(O,B)));
}
//扇形面积alpha*pi*r*r/2*pi
double sectorArea(point O,point A,point B,double r){
     
	double alpha=angle(O,A,B);
	return alpha*r*r/2;
}

int Seg_circle_relation(line v, circle C)//线段和圆的关系
{
     
    double dst = disOfPointToLine(C.c, v);
    if (sgn(dst - C.r) < 0)return 0;
    if (sgn(dst - C.r) == 0)return 1;//相切
    return 2;//圆外
}
int main()
{
     
    circle O;
    point A,B;
    scanf("%lf%lf%lf%lf%lf%lf%lf", &O.c.x, &O.c.y, &O.r, &A.x, &A.y, &B.x, &B.y);
    double area=PI*O.r*O.r;
    line v(A,B);
    if (Seg_circle_relation(v, O) == 1 || Seg_circle_relation(v, O) == 2)//不与圆相交
    {
     
        double sanArea = fabs(cross(O.c, A, B) / 2);
        double jiao = angle(O.c, A, B);
        double aa = area * (jiao / (2 * PI));
        double ans = area + sanArea - aa;
        printf("%.4lf\n", ans);
    }
    else//与圆相交
    {
     
        double lenOB = dis(O.c, B);
        double lenOA = dis(O.c, A);
        double lenA = sqrt(lenOA * lenOA - O.r * O.r);
        double lenB = sqrt(lenOB * lenOB - O.r * O.r);
        double AreaOA = lenA * O.r / 2.0;
        double AreaOB = lenB * O.r / 2.0;
        double ans = area + AreaOA + AreaOB;
        double ss1 = (lenOA * lenOA + O.r * O.r - lenA * lenA) / (2 * lenOA * O.r);
        double ss2 = (lenOB * lenOB + O.r * O.r - lenB * lenB) / (2 * lenOB * O.r);
        double jiaoA = acos(ss1);
        double jiaoB = acos(ss2);
        ans -= (jiaoA + jiaoB) / (2 * PI) * area;
        printf("%.4lf\n", ans);
    }
    return 0;
}

J.有点复杂的gcd问题

思路

第一眼,什么东西???第二眼,我还是先看看上面写的什么吧。一分钟后,算了看一下要求什么。第三眼,写那么多干甚莫啦,神经病呀!

只有a1到am全部相等时才满足条件。

也就是说直接1加到n,与k毫无关系,本来还用了个逆元和慢速乘,刚刚试了一下,直接乘也能过。giao!

代码

#include
using namespace std;
#define ll long long
#define pii pair
const ll mod=1e9+7;
const int maxn=1e6+5;
int main()
{
     
    int n,k;
    cin>>n>>k;
    ll ans=(n*(n+1))%mod/2;
    cout<<ans<<endl;
    return 0;
}

K.星星拜年

思路

搞了挺久的,基本不用dijstra选手,突然写多源汇最短路头都麻了,一直试图dfs优化看能不能过,无奈倒在了81.82分再上不去,没办法dijstra吧。

只要在0节点接上所有起点,n+1节点接上所有终点,再去跑dijstra就OK啦!维护一个到达该节点最短路径时最少礼物数数组cnt。

PS:一直都是队友写的图论,好久没写dijstra居然都不会写了,批评一下自己!

借鉴了一下madoka大佬的代码

代码

#include
using namespace std;
#define ll long long
#define pii pair
const ll mod=1e9+7;
const double eps=0.000001;
const double PI=acos(-1.0);
#define mk make_pair
struct node{
     
    ll p,c,k;
    bool operator<(const node &now)const{
     
        return c>now.c;
    }
};
ll n,m,n1,n2,k;
vector<pii>v[100007];
ll dist[100010],vis[100010],cnt[100010];
void bfs()
{
     
    priority_queue<node>q;
    q.push({
     0,0,0});
    while(!q.empty())
    {
     
        ll p=q.top().p;
        ll c=q.top().c;
        ll k=q.top().k;
        q.pop();
        if(vis[p]) continue;
        vis[p]=1;
        if(c<dist[p])
        {
     
            dist[p]=c;
            cnt[p]=k;
        }
        else if(c==dist[p]&&cnt[p]>k)
        {
     
            cnt[p]=k;
        }
        else{
     
            continue;
        }
        for(int i=0;i<v[p].size();i++)
        {
     
            ll to=v[p][i].first;
            ll co=v[p][i].second;
            cnt[to]=min(co+c,cnt[to]);
            q.push({
     to,co+c,k+1});
        }
    }
}
int main()
{
     
    cin>>n>>m>>n1>>n2>>k;
    memset(dist,0x3f,sizeof(dist));
    memset(cnt,0x3f,sizeof(cnt));
    for(int i=1;i<=n1;i++)
    {
     
        ll q;
        scanf("%lld",&q);
        v[0].push_back(mk(q,0));
    }
    for(int i=1;i<=n2;i++)
    {
     
        ll b;
        scanf("%lld",&b);
        v[b].push_back(mk(n+1,0));
    }
    for(int i=1;i<=m;i++)
    {
     
        ll a,b,c;
        scanf("%lld%lld%lld",&a,&b,&c);
        v[a].push_back(mk(b,c));
    }
    bfs();
    if(cnt[n+1]>k)
    {
     
        printf("we break up\n");
    }
    else{
     
        printf("%lld\n",k-cnt[n+1]+1);
    }
    return 0;
}

L.不要石头

网络流不会鸭

你可能感兴趣的:(比赛,程序设计,算法)