1. 程式人生 > >Intel Code Challenge Final Round (div.1 + div.2 combined) editorial

Intel Code Challenge Final Round (div.1 + div.2 combined) editorial

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;
}