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