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;
}