HDU多校八

总结:
这次过了一道签到题,其它的题目在讨论的时候还是没有讨论出好的方案,赛后认真补题!

1008

题意

给出半径为n的六边形(由半径为1的小六边形组成),从某一个小六边形出发由六个方向,找到一条转向次数最多的路径(用方向表示)遍历所有的六边形(一个六边形只访问一次)。

思路

分别分成奇数和偶数的情况,然后奇数内三层都是一样的,特殊处理一下六边形出来的第一个边,还有六边形的最后一条边;偶数的内两层都是一样的,然后特殊处理一下六边形的最后一条边。每次加2层是加4步。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int INF=0x3f3f3f3f;
const double pi=acos(-1.0),eps=1e-8;
const ll mod =  998244353;
const int maxn=1e5+5;
struct node
{
    double x,y;
} cir[5],p1,p2;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        if(n%2==0)
        {
            printf("461234");
            if(n>2)
            {
                int num=5;
                int xx=2;
                while(xx<n)
                {
                    printf("34");
                    int x=6,y=4;
                    for(int k=0; k<6; k++)
                    {
                        if(k<5)
                        {

                            for(int i=0; i<num; i++)
                            {
                                if(i%2==0)
                                    printf("%d",x);
                                else
                                    printf("%d",y);
                            }
                        }
                        else
                        {
                            for(int i=0; i<num-3; i++)
                            {
                                if(i%2==0)
                                    printf("%d",x);
                                else
                                    printf("%d",y);
                            }
                        }
                        x=(x)%6+1;
                        y=(y)%6+1;
                    }
                    printf("4");
                    num+=4;
                    xx+=2;
                }
            }
        }
        else
        {
            printf("546126231342453564");
            if(n>3)
            {
                int num=7;
                n-=2;
                while(n>1)
                {
                    printf("546");

                    int x=1,y=5;
                    for(int i=0; i<num-2; i++)
                    {
                        if(i%2==0)
                            printf("%d",x);
                        else
                            printf("%d",y);
                    }
                    x=(x)%6+1;
                    y=(y)%6+1;
                    for(int k=0; k<4; k++)
                    {
                        for(int i=0; i<num; i++)
                        {
                            if(i%2==0)
                                printf("%d",x);
                            else
                                printf("%d",y);
                        }
                        x=(x)%6+1;
                        y=(y)%6+1;
                    }
                    for(int i=0; i<num-1; i++)
                    {
                        if(i%2==0)
                            printf("%d",x);
                        else
                            printf("%d",y);
                    }
                n-=2;
                num+=4;
                }

            }
        }
        printf("\n");
    }

    return 0;
}

1003

题意

三个不同的点A(x1,y1),B(x2,y2),C(x3,y3),它们位于以O(0,0)为中心的圆上。想象一下从A开始,他画了一个圆穿过B,最后得到了C。确定他画的是顺时针还是逆时针。

思路

先求向量,再用叉积。

代码

#include<bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false),cin.tie(0);
#define ll long long
#define inf 0x3f3f3f3f
const int N=1e5+5;
//set<string>b;
//set<string>::iterator it;
double det(double x1,double y1,double x2,double y2)
{
	return x1*y2-x2*y1;
}
int main()
{
    IO;
    int T;
    double x1,y1,x2,y2,x3,y3;
    cin>>T;
    while(T--)
    {
    	cin>>x1>>y1>>x2>>y2>>x3>>y3;
    	double temp=det(x2-x1,y2-y1,x3-x2,y3-y2);
    	if(temp>0) cout<<"Counterclockwise\n";
    	else if(temp<0) cout<<"Clockwise\n";
	}
    return 0; 
}

1009

题意

给你一个长度为n的字符串s,让你判断是否存在一个k,使字符串分为连续的n/k个子串,要求子串之间两两互为循环同构。

思路

统计s串中不同种类字符的个数,取他们共同的最大公因数,再枚举其因数作为子串个数然后利用kmp算法判断n/k个子串是否两两之间为循环同构,注意k>1与字符种类数为1的情况要特判。

代码

#include <bits/stdc++.h>
#define ll long long
#define PII pair<int,int>
#define ls x<<1
#define rs x<<1|1
#define fi first
#define se second
#define pb push_back
#define inf 0x3f3f3f3f
using namespace std;
const int N=5e6+10;
int T,n;
char s[N];
int nxt[N];
bool kmp(char *t,char *s) {
	int ans=0;
	int i,j;
	int len1=strlen(t+1),len2=strlen(s+1);
	nxt[0]=nxt[1]=0;
	for(i=2,j=0;i<=len1;i++){
		while(j&&t[j+1]!=t[i])j=nxt[j];
		if(t[j+1]==t[i])++j;
		nxt[i]=j;
	}
	for(i=1,j=0;i<=len2;i++){
		while(j&&t[j+1]!=s[i])j=nxt[j];
		if(t[j+1]==s[i])++j;
		if(j==len1){
			ans++;j=nxt[j];
			return 1;
		}
	}
	return 0;
}
char a[N],b[N];
bool pd(int k) {
	if(k==1) return 0;
	int len=n/k;
	for(int i=1;i<=len;i++) {
		a[i]=s[i];
		a[i+len]=s[i];
	}
	a[2*len+1]='\0';
	for(int i=len;i<=n;i+=len) {
		for(int j=1;j<=len;j++) {
			b[j]=s[i+j];
		}
		b[len+1]='\0';
		if(kmp(b,a)==0) return 0;
	}
	return 1;
	
}
int main()
{
	//cwk;
	scanf("%d",&T);
	while(T--) {
		scanf("%d",&n);
		scanf("%s",s+1);
		int flag=0;
		for(int i=1;1ll*i*i<=n&&!flag;i++) {
			if(n%i==0) {
				flag|=pd(i);
				flag|=pd(n/i);
			}
		}
		if(!flag) puts("No");
		else puts("Yes");
	}

	return 0;
}


1006

题意

给你n个价格范围l,r,问最后没组价格的上下浮动能不能不超过k

思路

如果 i 是在 [l, r] 范围内, 那么 i + 1 必须要在 [l-k, r + k] 范围内.这是因为如果 i + 1 选了范围外的值, i 就无解了.
这样可以从左往右, 把左边的约束带到右边.再从右往左做一遍.最后剩下的区间应该就是可行域.因为题目只要求一种方案, 全部选最低的即可.复杂度 O(n)。

代码

#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
#define PI acos(-1)

using namespace std;
const int maxn = 1e5+5;
const ll mod = 1e9;
const double eps = 1e-6L;
ll n,k;
struct node
{
    ll l,r;
} a[maxn];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld %lld",&n,&k);
        for(int i=0; i<n; i++)
        {
            scanf("%lld %lld",&a[i].l,&a[i].r);
        }
        ll left=a[0].l,right = a[0].r;
        bool flag = true;
        for(int i=1; i<n; i++)
        {
            left = left-k;
            right = right+k;
            a[i].l = max(a[i].l,left);
            a[i].r = min(a[i].r,right);
            left = a[i].l;
            right = a[i].r;
            if(a[i].l>a[i].r)
            	flag = false;
        }
        left=a[n-1].l,right = a[n-1].r;
        for(int i=n-2; i>=0; i--)
        {
            left = left-k;
            right = right+k;
            a[i].l = max(a[i].l,left);
            a[i].r = min(a[i].r,right);
            left = a[i].l;
            right = a[i].r;
            if(a[i].l>a[i].r)
            	flag = false;
        }
        if(!flag)	puts("NO");
        else
        {
        	puts("YES");
        	for(int i=0; i<n; i++)
        	{
        		if(i)printf(" ");
				printf("%d",a[i].l);
			}
			puts("");
		}
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值