724A - Checking the Calendar

#include<stdio.h>
#include<string>
#include<iostream>
using namespace std;
string s1,s2;
int hs(string s)
{
    if(s=="monday") return 1;
    else if(s=="tuesday") return 2;
    else if(s=="wednesday") return 3;
    else if(s=="thursday") return 4;
    else if(s=="friday") return 5;
    else if(s=="saturday") return 6;
    else if(s=="sunday") return 7;
}
int main()
{
    cin>>s1>>s2;
    int a1=hs(s1),a2=hs(s2),pd=0;
    if(a1==a2||(a2-a1+7)%7==3||(a2-a1+7)%7==2) pd=1;
    if(pd) printf("YES");
    else printf("NO");
    return 0;
}

724B - Batch Sort

#include<stdio.h>
#include<algorithm>
using namespace std;
int x[21][21],yg[21],sf[21][21],bt[21];
int n,m;
bool bzmd()
{
    for(int i=1;i<=n;i++)
    {
        int s=0;
        for(int j=1;j<=m;j++)
        {    
            s+=x[i][j]!=yg[j];
            if(s>2) return 0;
        }
    }
    return 1;
}
int main()
{
    int pd=1;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&x[i][j]),bt[i]+=x[i][j]!=j;
    for(int i=1;i<=m;i++)
    for(int i=1;i<=n;i++)
        if(bt[i]>4)
        {
            printf("NO");
            return 0;
        }
        else if(bt[i]>2) pd=0;
    if(pd) 
    {
        printf("YES");
        return 0;
    }
    for(int i=1;i<=m;i++)
        yg[i]=i;
    for(int i=1;i<m;i++)
        for(int j=i+1;j<=m;j++)
        {
            swap(yg[i],yg[j]);
            if(bzmd())
            {
                printf("YES");
                return 0;
            }
            swap(yg[i],yg[j]);
        }
    printf("NO");
    return 0;
} 

724C - Ray Tracing

题目大意:

在一个nXm的平面里,光线从(0,0)以45度角出发,遇到边界则发生反射,遇到角时就停止。

在平面中有些监视器坐标为(xi,yi),问你光线第一次经过监视器的时间(光线每秒走根号2单位长度)

解题思路:

思考在物理中学习平面镜是虚像的问题

我们可以通过做对称保持光线一直在走直线

纵向将所有点关于x=k*n(k=1,2,3,....)做对称,

横向将所有点关于y=k*m(k=1,2,3,...)做对称。

然后我们思考监视器的横向坐标为k*n+xi或者k*n-xi

纵向为k*m+yi或者k*m-yi

由于光线45度出发

所以与光线经过的一定是横纵坐标相等的点

 也就是说横纵坐标相等

k1*n±xi=k2*m±yi

k1*n-k2*m=±(xi±yi)

此时就变成了一个关于k1,k2的不定方程组

就可以用exgcd求出一组解kk1,kk2

我们就可以得到通解为

k1=kk1-m/gcd(n,-m)*t;

k2=kk2-n/gcd(n,-m)*t;

t为整数

(这个不知道的还是去看看百科吧)

求出k1可能的最小正

之后只要再算出最小的正整数x,求出时间即可

至于xi,yi前面的正负,就把每种情况都算一遍。

#include<cstdio>
#include<algorithm>
typedef int int_;
#define int long long
using namespace std;
int n,m,jt,x,y;
int rd(){
    char c;
    while((c=getchar())<'0'||c>'9') ;
    int re=c-'0';
    while((c=getchar())>='0'&&c<='9') re=(re<<1)+(re<<3)+c-'0';
    return re;
}
int mi(int a,int b){
    return a>b?b:a;
}
int gcd(int a,int b){
    return b?gcd(b,a%b):a; 
}
void exgcd(int a,int b){
    if(!b) x=1,y=0;
    else{
        exgcd(b,a%b);
        int tx=y,ty=x-a/b*y;
        x=tx,y=ty;
    }
}
int js(int a,int b){
    int c=b-a; 
    if(c&1) return jt;
    c>>=1;
    int t=gcd(n,-m);
    if(c%t) return jt;
    exgcd(n,-m);
    x*=c/t;t=abs(m/t);
    x=(x%t+t)%t;
    int ti=2*n*x+a;
    if(ti<0||ti>jt) return jt;
    return ti;
}
int_ main(){
    n=rd(),m=rd();
    int k=rd();
    jt=n*m/gcd(m,n);
    while(k--){
        int a,b,ans=jt;
        scanf("%I64d%I64d",&a,&b);
        ans=mi(ans,js(a,b));
        ans=mi(ans,js(-a,b));
        ans=mi(ans,js(a,-b));
        ans=mi(ans,js(-a,-b));
        if(ans==jt) printf("-1\n");
        else printf("%I64d\n",ans);
    }
    return 0;
}

724D - Dense Subsequence

题目大意

给你一个序列s和一个整数m

对于每个s[i]可以选择或者不选

要求每个长度为m的子串中必须有一个元素是被选择的

问你所有选择的方式中

选择的所有s[i]排序后字典序最小的方式是哪个

要求输出最后排序的字符串

 

解题思路

首先我们思考

aab没有aaab优

aaab比aaabb优

什么意思呢?

假设这次我们所要选择的字符串至少为b

那么所有a都选上才更优

并且选的b越少越优

所以我们首先贪心求出最少要加入那些字符(尽量使用小字符的前提下),并且记录加入的最大字符

然后把所有比它小的字符都加入最后的字符串再排序就可以了

贪心的过程其实就是看目前还没有被覆盖的最靠左的长度为m的子串中的最小字符(同样小就要尽量靠右)是哪个,然后在到下个未覆盖的开始找

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+5;
char s[N],a[N];
bool vis[N];
int to[30];
int main(){
    int m,n,l=1,l1=0,mx=0;
    scanf("%d%s",&m,s+1);
    n=strlen(s+1);
    while(l+m-1<=n){
        int mi=l;
        for(int i=l+1;i<=l+m-1;++i)
            if(s[i]<=s[mi]) mi=i;
        a[l1++]=s[mi];
        l=mi+1;
        vis[mi]=1;
        if(s[mi]>mx) mx=s[mi];
    }
    for(int i=1;i<=n;++i) if(s[i]<mx&&!vis[i]) a[l1++]=s[i];
    sort(a,a+l1);
    printf("%s",a);
    return 0;
}