这次不是隔天,正好比赛是在8点开始,而且听说有车队,就打了一下,结果似乎不是那么的顺利。
A. Checking the Calendar
题意:题目给你两个星期,假如一个月的第一天是第一个星期,那么下个月的第一天有没有可能是第二个星期。月份只有可能是非闰年的月份。
分析:很简单的签到题,将给你的星期换成数字,分别为a和b(周日表示为0)。那么如果a==b或者(a+2)mod7==b或者(a+3)mod7==b中间有一个等式成立的话,就是YES(因为非闰年的月份只可能有28、30、31天)。
#include <map>
#include <set>
#include <ctime>
#include <stack>
#include <cmath>
#include <queue>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <fstream>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define maxn 270000+10
#define SIZE 10000+5
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define clr(x,y) memset(x,y,sizeof(x))
#define rep(i,n) for(int i=0;i<(n);i++)
#define repf(i,a,b) for(int i=(a);i<=(b);i++)
#define pii pair<int,int>
#define mp make_pair
#define FI first
#define SE second
#define IT iterator
#define PB push_back
#define Times 10
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const double eps = 1e-14;
const double pi = acos(-1.0);
const ll mod = 10007;
const int inf = 0x3f3f3f3f;
const ll INF = (ll)1e18+300;
const double delta = 0.98;
inline void RI(int& x)
{
x=0;
char c=getchar();
while(!((c>='0'&&c<='9')||c=='-'))c=getchar();
bool flag=1;
if(c=='-')
{
flag=0;
}
while(c<='9'&&c>='0')
{
x=x*10+c-'0';
c=getchar();
}
if(!flag)x=-x;
}
char a[20],b[20];
int cal(char* str){
if(str[0]=='m')return 1;
else if(str[0]=='t'){
if(str[1]=='u')return 2;
else return 4;
}
else if(str[0]=='w')return 3;
else if(str[0]=='f')return 5;
else if(str[1]=='a')return 6;
else return 0;
}
int main(){
scanf("%s",a);
scanf("%s",b);
int aa=cal(a);
int bb=cal(b);
if(aa==bb||(aa+2)%7==bb||(aa+3)%7==bb)puts("YES");
else puts("NO");
return 0;
}
B. Batch Sort
题意:给出一个数字矩阵n*m,每一行是从1到m的所有数字的一个排序。问某个数字矩阵可不可以通过每行不超过一次的交换两个数的位置,和不超过一次的将两列整体交换。使得最后操作玩的数字矩阵每一行都是递增的
分析:看见数据范围很小,然后思考一下应该没有比暴力更好的方法了。每次先枚举一下交换的两列(n^2),当然也要考虑不交换的情况,特判一下。交换之后,对每一行扫描(n),如果位置(n)不对的地方有2个以上,那么不可以通过一次交换使得最后这一行是递增的。如果对于每一行都只有不超过2个的位置不同,那么这种交换就是成功的。最后的复杂度是o(n^4)
#include <map>
#include <set>
#include <ctime>
#include <stack>
#include <cmath>
#include <queue>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <fstream>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define maxn 270000+10
#define SIZE 10000+5
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define clr(x,y) memset(x,y,sizeof(x))
#define rep(i,n) for(int i=0;i<(n);i++)
#define repf(i,a,b) for(int i=(a);i<=(b);i++)
#define pii pair<int,int>
#define mp make_pair
#define FI first
#define SE second
#define IT iterator
#define PB push_back
#define Times 10
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const double eps = 1e-14;
const double pi = acos(-1.0);
const ll mod = 10007;
const int inf = 0x3f3f3f3f;
const ll INF = (ll)1e18+300;
const double delta = 0.98;
inline void RI(int& x)
{
x=0;
char c=getchar();
while(!((c>='0'&&c<='9')||c=='-'))c=getchar();
bool flag=1;
if(c=='-')
{
flag=0;
}
while(c<='9'&&c>='0')
{
x=x*10+c-'0';
c=getchar();
}
if(!flag)x=-x;
}
int n,m;
int dat[22][22];
bool check(){
for(int i=0;i<n;i++){
int num=0;
for(int j=0;j<m;j++)
if(dat[i][j]!=j+1)
num++;
if(num>2)return false;
}
puts("YES");
return true;
}
int main(){
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
scanf("%d",&dat[i][j]);
if(check())return 0;
for(int i=0;i<m;i++)
for(int j=i+1;j<m;j++){
for(int k=0;k<n;k++)
swap(dat[k][i],dat[k][j]);
if(check())return 0;
for(int k=0;k<n;k++)
swap(dat[k][i],dat[k][j]);
}
puts("NO");
return 0;
}
C. Ray Tracing
题意:在一个n*m的坐标图上给你k个点,从(0,0)向(1,1)射出一束镭射光线,镭射光线的速度是每秒2√镭射光线碰到边界的时候满足物理定理进行反射(入射角等于出射角),当镭射光线射到四个角落的时候结束(不再反射)问每个点能不能被光线经过,不能经过输出-1,可以经过输出第一次经过的时间
分析:人家很快的推出公式了,因为是翻转不是平移,所以在系数上要乘以2。对于每个查询点(a,b),公式是2∗m∗x±a=2∗n∗y±b,对于四种情况求出等号左边的最小整数解。妈蛋,本来有了公式是很好写的,但是就是各种小错误
#include <map>
#include <set>
#include <ctime>
#include <stack>
#include <cmath>
#include <queue>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <fstream>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define maxn 270000+10
#define SIZE 10000+5
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define clr(x,y) memset(x,y,sizeof(x))
#define rep(i,n) for(int i=0;i<(n);i++)
#define repf(i,a,b) for(int i=(a);i<=(b);i++)
#define pii pair<int,int>
#define mp make_pair
#define FI first
#define SE second
#define IT iterator
#define PB push_back
#define Times 10
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const double eps = 1e-14;
const double pi = acos(-1.0);
const ll mod = 10007;
const int inf = 0x3f3f3f3f;
const ll INF = (ll)1e18+300;
const double delta = 0.98;
inline void RI(int& x)
{
x=0;
char c=getchar();
while(!((c>='0'&&c<='9')||c=='-'))c=getchar();
bool flag=1;
if(c=='-')
{
flag=0;
}
while(c<='9'&&c>='0')
{
x=x*10+c-'0';
c=getchar();
}
if(!flag)x=-x;
}
ll exgcd(ll a,ll b,ll& x,ll& y)
{
if(!b)
{
x=1;
y=0;
return a;
}
ll r=exgcd(b,a%b,y,x);
y-=a/b*x;
return r;
}
bool linear_equation(ll a,ll b,ll ca,ll cb,ll& ans)
{
ll x,y,d;
ll c=ca+cb;
d=exgcd(a,b,x,y);
if(c%d)return false;
ll k=c/d;
ll g=b/d;
if(g<0)g=-g;
g*=a;
x*=k;y*=k;
ans=a*x-cb;
ans=(ans%g+g)%g;
return true;
}
int dir[4][2]={1,1,-1,1,1,-1,-1,-1};
int main(){
ll n,m,k;
scanf("%lld %lld %lld",&n,&m,&k);
while(k--){
ll a,b;
scanf("%lld %lld",&a,&b);
ll ans=(ll)1e18;
ll x,y,d,xx;
for(int i=0;i<4;i++)
if(linear_equation(2*m,-2*n,dir[i][0]*a,dir[i][1]*b,xx))
ans=min(ans,xx);
if(ans==(ll)1e18)puts("-1");
else printf("%lld\n",ans);
}
return 0;
}
D. Dense Subsequence
题意:给一个数m和字母字符串s,从s中选择一些位置,要求每连续m个字母的子串都有一个被选中的位置。把这些位置的字符选出来重排列后使得字典序最小?
分析:一开始的时候,随便乱做,看漏了很多性质。后来才发现只需要找到一个最小的字母k(k表示某个字母,并不一定是k),能够使得小于k的位置和某一部分等于k的位置。这些位置存在于任何一个m连续子串之中。其中小于k的字母必须按照原串中的个数输出,然后等于k的字母按照贪心从前往后(这里写法很精妙,我一开始写的不好)。反正就只有26个字母,那么我们就是枚举一下字母k
#include <map>
#include <set>
#include <ctime>
#include <stack>
#include <cmath>
#include <queue>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <fstream>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define maxn 100000+10
#define SIZE 10000+5
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define clr(x,y) memset(x,y,sizeof(x))
#define rep(i,n) for(int i=0;i<(n);i++)
#define repf(i,a,b) for(int i=(a);i<=(b);i++)
#define pii pair<int,int>
#define mp make_pair
#define FI first
#define SE second
#define IT iterator
#define PB push_back
#define Times 10
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const double eps = 1e-14;
const double pi = acos(-1.0);
const ll mod = 10007;
const int inf = 0x3f3f3f3f;
const ll INF = (ll)1e18+300;
const double delta = 0.98;
inline void RI(int& x)
{
x=0;
char c=getchar();
while(!((c>='0'&&c<='9')||c=='-'))c=getchar();
bool flag=1;
if(c=='-')
{
flag=0;
}
while(c<='9'&&c>='0')
{
x=x*10+c-'0';
c=getchar();
}
if(!flag)x=-x;
}
char dat[maxn];
int n,m,num[300];
int solve(int x){
int pre=-1,posx=-1,cnt=0;
for(int i=0;i<n;i++){
if(dat[i]<x)pre=posx=i;
if(dat[i]==x)posx=i;
if(i==pre+m){
if(posx==pre)return -1;
cnt++;
pre=posx;
}
}
return cnt;
}
int main(){
scanf("%d %s",&m,dat);
n=strlen(dat);
for(int i=0;i<n;i++)num[dat[i]]++;
for(int i='a';i<='z';i++){
int x=solve(i);
if(x!=-1){
for(int j='a';j<i;j++)
for(int k=0;k<num[j];k++)
putchar(j);
for(int j=0;j<x;j++)
putchar(i);
puts("");
return 0;
}
}
return 0;
}