总结:
这次过了一道签到题,其它的题目在讨论的时候还是没有讨论出好的方案,赛后认真补题!
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;
}