2020年浙江理工大学校赛同步赛

题目
A题意:定义一个自然数,若它的质因数至少是两重的,则称为漂亮数,若相邻两个自然数都是“漂亮数”, 就称它们为“孪生漂亮数”。输出[n,m]区间所有孪生漂亮数。
解法:类似质因数分解,如果存在某一质因数判断该质因数是否是两个以上。

int n , m ;

bool eluer(int x){
    rep(i , 2 , sqrt(x)){
        if(x % i == 0){
            int cnt = 0 ;
            while(x % i == 0){
                x /= i ;
                cnt++;
            }
            if(cnt == 1) return false;
        }
    }
    if(x > 1) return false;
    return true;
}

void solve(){
    scanf("%lld%lld" , &n , &m);
    vector<int>a;
    rep(i , n , m){
        if(eluer(i)){
            a.pb(i);
        }
    }
    int flag = 0 ;
    for(int i = 1 ; i < size(a) ; i++){
        if(a[i] - a[i-1] == 1){
            flag = 1 ;
            cout << a[i-1] << " " << a[i] << endl;
        }
    }
    if(!flag){
        cout << "no find" << endl;
    }
}

B题意:给出n列2行格子,在格子中填0-9中任意数,问满足任意相邻3列总和为k的填法。
解法:枚举前三列的取值,确定了前三列的取值,之后列取值也随之确定。

const int maxn = 1e5+9;
int a[maxn][3];
int b[4] , c[4];//记录前三个列的和以及方案数

pii get(int i){//获取第i列的范围
    if(a[i][0] == -1 && a[i][1] == -1) return {0,18};
    if(a[i][0] != -1 && a[i][1] != -1) return {a[i][0] + a[i][1] , a[i][0] + a[i][1]};
    return {a[i][0] + a[i][1] + 1 , a[i][0] + a[i][1] + 10};
}
int solve(int i , int j){//i列和等于j的方案数
    if(a[i][0] == -1 && a[i][1] == -1){
        if(j >= 0 && j <= 9){
            return j+1;
        }else if(j != 18){
            return 10 - j % 9 ;
        }else{
            return 1;
        }
    }else{
        return 1 ;
    }
}

void solve(){
    ME(a , -1);
    int n , sum , m ;
    scanf("%lld%lld%lld" , &n , &sum , &m);
    rep(i , 1 , m){
        int x , y , w ;
        scanf("%lld%lld%lld" , &x , &y , &w);
        a[x][y] = w ;
    }
    pii x = get(0) , y = get(1) , z = get(2);
    int ans = 0 ;
    rep(i , x.fi , x.se){//枚举第一列范围
        b[0] = i ;
        c[0] = solve(0 , i);
        rep(j , y.fi , y.se){//枚举第二列范围
            b[1] = j ;
            c[1] = solve(1 , j);
            int k = sum - i - j ;//根据总和确定第三列值
            if(k > z.se || k < z.fi) continue;//判断是否在第三列的范围当中
            b[2] = k ;
            c[2] = solve(2 , k);
            int res = c[0] * c[1] * c[2] ;//前三列的种数
            rep(l , 3 , n-1){
                pii p = get(l);//获取第l列取值范围
                if(b[l%3] < p.fi || b[l%3] > p.se){//第四列与第一列和一致,第一列取值是否在l列的取值范围内
                    res = 0 ;
                    break;
                }
                res = (res * solve(l , b[l%3]))%  mod ;
            }
            ans  = (ans + res) % mod ;
        }
    }
    cout << ans << endl;
}

C题意:模拟。

const int N = 4e2+9;
const int maxn = 29;
int t , n , m ;
struct grid{
    int t , d ;//土地类型和土壤时间
}g[maxn][maxn];
int sl , wl;//羊和狼的数量
struct Sheep{
    int x , y , d , l;//羊的坐标、饥饿度,是否存活
}s[N];
struct Wolf{
    int x , y , d , l;//同上
}w[N];

void cow(){//土壤长草
    rep(i , 1 , n){
        rep(j , 1 , m){
            if(g[i][j].t == 3){//土壤类型
                g[i][j].d++;
                if(g[i][j].d > 3){//坑点1:三天后长草
                    g[i][j].t = 2 ;
                }
            }
        }
    }
}
void sw_move(){//羊移动、狼移动
    rep(i , 1 , sl){
        if(s[i].l == 1){//存活的羊
            s[i].x++;
            if(s[i].x == n+1) s[i].x = 1 ;
            s[i].d++;//羊饥饿度增加
        }
    }
    rep(i , 1 , wl){
        if(w[i].l == 1){//存活的狼
            w[i].y++;
            if(w[i].y == m+1) w[i].y = 1 ;
            w[i].d++;//狼的饥饿度增加
        }
    }
}

void eatsheep(){//羊吃狼
    rep(i , 1 , sl){
        rep(j , 1 , wl){
            if(s[i].l == 1 && w[j].l == 1 && s[i].x == w[j].x && s[i].y == w[j].y){//羊和狼位于同一土壤
                s[i].l = 0 ;//狼吃羊
                g[s[i].x][s[i].y].t = 1 ;//该地变为残骸
                w[j].d = 0 ;
            }
        }
    }
    rep(i , 1 , wl){
        if(w[i].l == 1){
            if(w[i].d>=10){//狼饿死
                w[i].l = 0 ;
                g[w[i].x][w[i].y].t = 1 ;
            }
        }
    }
}

void eatcow(){//羊吃草
    rep(i , 1 , sl){
        if(s[i].l == 1){
            int x = s[i].x , y = s[i].y ;
            if(g[x][y].t == 2){//羊吃草
                s[i].d = 0 ;
                g[x][y].t = 3 ;
                g[x][y].d = 0;
            }else{
                if(s[i].d >= 5){//羊饿死
                    s[i].l = 0 ;
                    g[x][y].t = 1 ;
                }
            }
        }
    }
}
void turn(){//坑点2
    rep(i , 1 , n){
        rep(j , 1 , m){
            if(g[i][j].t == 3 && g[i][j].d >= 3){//T天后土壤状态是否长草
                g[i][j].t = 2;
            }
        }
    }
}

void solve(){
     scanf("%lld%lld%lld" , &t , &n , &m);
     rep(i , 1 , n){
         rep(j , 1 , m){
             char c ;
             cin >> c;
             g[i][j].t = 3 , g[i][j].d = 0 ;//初始都为土壤
             if(c == 'S'){
                 s[++sl].x = i , s[sl].y = j , s[sl].d = 0 , s[sl].l = 1;
             }else if(c == 'W'){
                 w[++wl].x = i , w[wl].y = j , w[wl].d = 0 , w[wl].l = 1;
             }
         }
     }
     rep(i , 1 , t){
         cow();
         sw_move();
         eatsheep();
         eatcow();
     }
     turn();
     set<pii>sh , wo;
     rep(i , 1 , sl){//记录存活的羊的坐标
         if(s[i].l == 1){
             sh.insert(mp(s[i].x , s[i].y));
         }
     }
     rep(i, 1 , wl){//记录存活的狼的坐标
         if(w[i].l == 1){
             wo.insert(mp(w[i].x , w[i].y));
         }
     }
     rep(i , 1 , n){
         rep(j , 1 , m){
             if(sh.count(mp(i , j))){//该坐标存在羊
                 printf("S");
             }else if(wo.count(mp(i , j))){//该坐标存在狼
                 printf("W");
             }else if(g[i][j].t == 1){
                 printf("*");
             }else if(g[i][j].t == 2){
                 printf("#");
             }else{
                 printf(".");
             }
         }
         printf("\n");
     }
}

D题意:求圆与矩形相交的面积。
https://www.cnblogs.com/qywhy/p/9772681.html

#include<bits/stdc++.h>
#define inf 1000000000000
#define M 100009
#define eps 1e-12
#define PI acos(-1.0)
using namespace std;
struct Point
{
    double x,y;
    Point(){}
    Point(double xx,double yy){x=xx;y=yy;}
    Point operator -(Point s){return Point(x-s.x,y-s.y);}
    Point operator +(Point s){return Point(x+s.x,y+s.y);}
    double operator *(Point s){return x*s.x+y*s.y;}
    double operator ^(Point s){return x*s.y-y*s.x;}
}p[M];
double max(double a,double b){return a>b?a:b;}
double min(double a,double b){return a<b?a:b;}
double len(Point a){return sqrt(a*a);}
double dis(Point a,Point b){return len(b-a);}//两点之间的距离
double cross(Point a,Point b,Point c)//叉乘
{
    return (b-a)^(c-a);
}
double dot(Point a,Point b,Point c)//点乘
{
    return (b-a)*(c-a);
}
int judge(Point a,Point b,Point c)//判断c是否在ab线段上(前提是c在直线ab上)
{
    if (c.x>=min(a.x,b.x)
       &&c.x<=max(a.x,b.x)
       &&c.y>=min(a.y,b.y)
       &&c.y<=max(a.y,b.y)) return 1;
    return 0;
}
double area(Point b,Point c,double r)
{
    Point a(0.0,0.0);
    if(dis(b,c)<eps) return 0.0;
    double h=fabs(cross(a,b,c))/dis(b,c);
    if(dis(a,b)>r-eps&&dis(a,c)>r-eps)//两个端点都在圆的外面则分为两种情况
    {
        double angle=acos(dot(a,b,c)/dis(a,b)/dis(a,c));
        if(h>r-eps) return 0.5*r*r*angle;else
        if(dot(b,a,c)>0&&dot(c,a,b)>0)
        {
            double angle1=2*acos(h/r);
            return 0.5*r*r*fabs(angle-angle1)+0.5*r*r*sin(angle1);
        }else return 0.5*r*r*angle;
    }else
        if(dis(a,b)<r+eps&&dis(a,c)<r+eps) return 0.5*fabs(cross(a,b,c));//两个端点都在圆内的情况
        else//一个端点在圆上一个端点在圆内的情况
        {
            if(dis(a,b)>dis(a,c)) swap(b,c);//默认b在圆内
            if(fabs(dis(a,b))<eps) return 0.0;//ab距离为0直接返回0
            if(dot(b,a,c)<eps)
            {
                double angle1=acos(h/dis(a,b));
                double angle2=acos(h/r)-angle1;
                double angle3=acos(h/dis(a,c))-acos(h/r);
                return 0.5*dis(a,b)*r*sin(angle2)+0.5*r*r*angle3;
            }else
            {
                double angle1=acos(h/dis(a,b));
                double angle2=acos(h/r);
                double angle3=acos(h/dis(a,c))-angle2;
                return 0.5*r*dis(a,b)*sin(angle1+angle2)+0.5*r*r*angle3;
            }
        }
}
int main()
{
    int T,n=4;
    double rx,ry,R;
    //scanf("%d",&T);
    //for (int ii=1;ii<=T;ii++)
    //{
        scanf("%lf%lf%lf",&rx,&ry,&R);
        scanf("%lf%lf%lf%lf",&p[1].x,&p[1].y,&p[3].x,&p[3].y);
        p[2].x=p[1].x;p[2].y=p[3].y;
        p[4].x=p[3].x;p[4].y=p[1].y;
        p[5]=p[1];
        Point O(rx,ry);
        for (int i=1;i<=n+1;i++) p[i]=p[i]-O;
        O=Point(0,0);
        double sum=0;
        for (int i=1;i<=n;i++)
        {
            int j=i+1;
            double s=area(p[i],p[j],R);
            if (cross(O,p[i],p[j])>0) sum+=s;else sum-=s;
        }
        printf("%.4lf\n" , fabs(sum));
    //}
    return 0;
}

E题意:在一条直线上给出n个摊位的坐标,要使的任意两个摊位的坐标距离正好是k米,问摊位最少移动距离为多少。
解法:中位数原理,所有摊位向中位数靠拢。

int n , m ;
void solve(){
    int n , k ;
    scanf("%lld%lld" , &n , &k);
    vector<int>a(n);
    rep(i , 0 , n-1){
        cin >> a[i];
    }
    sort(all(a));
    int mid = size(a)/2;
    int t = mid-1 , d = a[mid]-k , sum = 0;//摊位下标,该摊位该去的位置
    while(t>=0){
        sum += abs(d-a[t]);
        d -= k ;
        t--;
    }
    t = mid + 1 , d = a[mid]+k ;
    while(t < size(a)){
        sum += abs(d-a[t]);
        d += k ;
        t++;
    }
    cout << sum << endl;
}
posted @ 2020-06-23 12:30  无名菜鸟1  阅读(242)  评论(0编辑  收藏  举报