我的隔天Codeforces——Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined)

这次不是隔天,正好比赛是在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;//1e9+7;
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(){
    //freopen("d:\\acm\\in.in","r",stdin);
    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;//1e9+7;
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(){
    //freopen("d:\\acm\\in.in","r",stdin);
    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),公式是 2mx±a=2ny±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;//1e9+7;
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;
}

/*--------------------------------------------------*/

//对于不定整数方程pa+qb=c,若 c mod Gcd(a, b)=0,则该方程存在整数解,否则不存在整数解
//p = p1 + b/Gcd(a, b) * t 
//q = q1 - a/Gcd(a, b) * t(其中t为任意整数,正负皆可)
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(){
    //freopen("d:\\acm\\in.in","r",stdin);
    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;//1e9+7;
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(){
    //freopen("d:\\acm\\in.in","r",stdin);
    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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值