此文章可以使用目錄功能喲↑(點擊上方[+])
再一次卡在C題上,考查的居然是初中的科學知識,不過能漲一波分也是蠻開心的...
鏈接→Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined)
Problem A-Checking the Calendar
Accept: 0 Submit: 0
Time Limit: 1 second Memory Limit : 256 megabytes
Problem Description
You are given names of two days of the week.
Please, determine whether it is possible that during somenon-leap year the first day of some month was equal to the first day of the week you are given, while the first day ofthe next month was equal to the second day of the week you are given.Both months should belong to one year.
In this problem, we consider the Gregorian calendar to be used. The number of months in this calendar is equal to 12. The number of days in months during any non-leap year is: 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31.
Names of the days of the week are given with lowercase English letters: "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday".
Input
The input consists of two lines, each of them containing the name of exactly one day of the week. It's guaranteed that each string in the input is from the set "monday", "tuesday", "wednesday", "thursday",
"friday", "saturday", "sunday".
Output
Print "YES" (without quotes) if such situation is possible during some non-leap year. Otherwise, print "NO" (without quotes).
Sample Input
tuesday
sunday
sunday
saturday
tuesday
Sample Output
YES
YES
Hint
In the second sample, one can consider February 1 and March 1 of year 2015. Both these days were Sundays.
In the third sample, one can consider July 1 and August 1 of year 2017. First of these two days is Saturday, while the second one is Tuesday.
Problem Idea
解題思路:
【題意】
給你兩個字符串a和b,分別表示一個星期中的某一天
問是否存在這麼一種情況,一個非閏年中某個月的第一天是a,下個月的第一天是b
【類型】
簽到題,取模
【分析】
因爲是非閏年,一個月的天數只有三種情況:28、30、31
①對於只有28天的一個月,恰好是四周時間,顯然該月第一天和下個月第一天是一個星期中的同一天
②對於有30天的一個月,四周多兩天,故只要b比a多兩天就可以了
③對於有31天的一個月,同理①和②
當然,一開始要先處理星期的問題,出題人比較人性化,給出了星期一到星期日的英文寫法,不然英語水平不好的又得苦惱一會兒了
【時間複雜度&&優化】
O(1)
題目鏈接→Codeforces Problem 724A Checking the Calendar
Source Code
/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-9
#define LL long long
#define PI acos(-1.0)
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 100005;
const int M = 100005;
const int inf = 1000000007;
const int mod = 20160519;
map<string,int> m;
string a,b;
int main()
{
int k;
m["monday"]=1;
m["tuesday"]=2;
m["wednesday"]=3;
m["thursday"]=4;
m["friday"]=5;
m["saturday"]=6;
m["sunday"]=7;//預處理
cin>>a>>b;
k=(m[b]-m[a]+7)%7;
//printf("%d\n",k);
if(k==3||k==2||k==0)
puts("YES");
else
puts("NO");
return 0;
}
Problem B-Batch Sort
Accept: 0 Submit: 0
Time Limit: 2 seconds Memory Limit : 256 megabytes
Problem Description
You are given a table consisting of n rows and m columns.
Numbers in each row form a permutation of integers from 1 to m.
You are allowed to pick two elements in one row and swap them, butno more than once for each row. Also, no more than once you are allowed to pick two columns and swap them. Thus, you are allowed to perform from 0 to n + 1 actions in total.Operations can be performed in any order.
You have to check whether it's possible to obtain the identity permutation 1, 2, ..., m in each row. In other words, check if one can perform some of the operation following the given rules and make each row sorted in increasing order.
Input
The first line of the input contains two integers n and m (1 ≤ n, m ≤ 20) — the number of rows and the number of columns in the given table.
Each of next n lines contains m integers — elements of the table. It's guaranteed that numbers in each line form a permutation of integers from 1 to m.
Output
If there is a way to obtain the identity permutation in each row by following the given rules, print "YES" (without quotes) in the only line of the output. Otherwise, print "NO" (without quotes).
Sample Input
1 3 2 4
1 3 4 2
4 4
1 2 3 4
2 3 4 1
3 4 1 2
4 1 2 3
3 6
2 1 3 4 5 6
1 2 4 3 5 6
1 2 3 4 6 5
Sample Output
NO
YES
Hint
In the first sample, one can act in the following way:
1.Swap second and third columns. Now the table is
1 2 3 4
1 4 3 2
2.In the second row, swap the second and the fourth elements. Now the table is
1 2 3 4
1 2 3 4
Problem Idea
解題思路:
【題意】
給你一個n*m的矩陣
每行均是1~m的一個排列
現在規定:
①矩陣的每行最多隻能交換一次某兩個位置的數
②最多隻能交換一次矩形某兩列的數
問最終矩形的每一行的數是否都能夠遞增
【類型】
暴力
【分析】
如果此題沒有交換某兩列的這種操作,相信會簡單得多
因爲這樣子的話我只要判斷第i(1≤i≤n)行是不是最多隻有兩處s[i][j]!=j的位置就可以判定最終能否使得每一行的數都遞增
但是,此題多了交換某兩列的操作,當然,因爲矩陣的規模比較小,做法還是比較簡單的
首先二重循環暴力,交換第i列和第j列(1≤i<j≤m),然後再判斷在交換第i列和第j列之後,是否每一行最多隻有兩處不符合遞增的位置
需注意的是,不執行列交換的這種情況也要判一下
【時間複雜度&&優化】
O(N*M*M*M)
題目鏈接→Codeforces Problem 724B Batch Sort
Source Code
/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-9
#define LL long long
#define PI acos(-1.0)
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 25;
const int M = 100005;
const int inf = 1000000007;
const int mod = 20160519;
int n,m,s[N][N];
bool check()
{
int i,j,k;
for(i=1;i<=n;i++)
{
for(k=0,j=1;j<=m;j++)
if(s[i][j]!=j)
k++;
if(k>2)
return false;
}
return true;
}
int main()
{
int i,j,k;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%d",&s[i][j]);
if(check())//不執行列交換的情況
{
puts("YES");
return 0;
}
for(i=1;i<=m;i++)
for(j=i+1;j<=m;j++)
{
for(k=1;k<=n;k++)
swap(s[k][i],s[k][j]);
if(check())
{
puts("YES");
return 0;
}
for(k=1;k<=n;k++)
swap(s[k][i],s[k][j]);
}
puts("NO");
return 0;
}
Problem C-Ray Tracing
Accept: 0 Submit: 0
Time Limit: 2 seconds Memory Limit : 256 megabytes
Problem Description
There are k sensors located in the rectangular room of size n × m meters. The i-th sensor is located at point (xi, yi). All sensors are located at distinct points strictly inside the rectangle.
Opposite corners of the room are located at points (0, 0) and (n, m). Walls of the room are parallel to coordinate axes.
At the moment 0, from the point (0, 0) the laser ray is released in the direction of point (1, 1). The ray travels with a speed ofmeters per second. Thus, the ray will reach the point (1, 1) in exactly one second after the start.
When the ray meets the wall it's reflected by the rule that the angle of incidence is equal to the angle of reflection. If the ray reaches any of the four corners, it immediately stops.
For each sensor you have to determine the first moment of time when the ray will pass through the point where this sensor is located. If the ray will never pass through this point, print - 1 for such sensors.
Input
The first line of the input contains three integers n, m and k (2 ≤ n, m ≤ 100 000, 1 ≤ k ≤ 100 000) — lengths of the room's walls and the number of sensors.
Each of the following k lines contains two integers xi and yi (1 ≤ xi ≤ n - 1, 1 ≤ yi ≤ m - 1) — coordinates of the sensors. It's guaranteed that no two sensors are located at the same point.
Output
Print k integers. The i-th of them should be equal to the number of seconds when the ray first passes through the point where the i-th sensor is located, or - 1 if this will never happen.
Sample Input
1 1
1 2
2 1
2 2
3 4 6
1 1
2 1
1 2
2 2
1 3
2 3
7 4 5
1 3
2 2
5 1
5 3
4 3
Sample Output
-1
-1
2
1
-1
-1
2
5
-1
13
2
9
5
-1
Hint
In the first sample, the ray will consequently pass through the points (0, 0), (1, 1), (2, 2), (3, 3). Thus, it will stop at the point (3, 3) after 3 seconds.
In the second sample, the ray will consequently pass through the following points: (0, 0), (1, 1), (2, 2), (3, 3), (2, 4), (1, 3), (0, 2), (1, 1), (2, 0), (3, 1), (2, 2), (1, 3), (0, 4). The ray will stop at the point (0, 4) after 12 seconds. It will reflect
at the points (3, 3), (2, 4), (0, 2), (2, 0) and (3, 1).
Problem Idea
解題思路:
【題意】
m*n的矩形內部有k個點,一條光線從(0,0)出發,向(1,1)方向以米每秒運動
當光線碰到壁時會反射,碰到矩形的四個角時結束運動
問第一次經過那k個點的時間
若一個點不可達,則輸出-1
【類型】
鏡面反射,循環節
【分析】
剛開始拿到這道題,感覺除了暴力沒其他想法,但是矩形規模有點大,暴力應該會超時,所以放棄暴力的想法
那我們嘗試找找規律
當n=9,m=8時,光線的運動路線如下
當n=9,m=7時,光線的運動路線如下
經過幾種情況的嘗試,也並沒有發現有什麼竅門
這時,需要從反射這個突破口下功夫
相信大家應該知道鏡面反射中虛像的概念:
A'即爲虛像
此題就可根據虛像的性質進行處理
以樣例二爲例(n=3,m=4)
顯然,對於點(x,y),關於右壁的對稱點有兩類:
①(x+2kn,y) k=0,1,2,…
②(2(k+1)n-x,y) k=0,1,2,…
而對稱點還要判斷是否出現在上升光線上 or 下降光線上
四種情況取時間最少的就是光線到達該點的時間
四種情況分別爲:①x+2kn-y②x+2kn+y③2(k+1)n-x-y④2(k+1)n-x+y
那麼如何判斷點(x+2kn,y)在上升光線上呢?
當且僅當(x+2kn-y)%(2m)==0存在非負整數解時,在上升光線上
同理,當且僅當(x+2kn+y)%(2m)==0存在非負整數解時,在下降光線上
而要求第一次的時間,顯然要求滿足上式的最小k,那麼我們可以通過預處理循環節(2kn)%(2m),以減小時間複雜度
這題的方法解釋起來有點難,但理解了就會發現做法很簡單
以上提供的是個人的一點看法,方便大家理解,如果還有不明白之處,歡迎提出,博主會盡快予以解答
【時間複雜度&&優化】
O(max{N,M,K})
題目鏈接→Codeforces Problem 724C Ray Tracing
Source Code
/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-9
#define LL long long
#define PI acos(-1.0)
#define bitnum(a) __builtin_popcount(a)
using namespace std;
//const int N = 100005;
//const int M = 26;
const __int64 inf = 1e18;
const int mod = 20160519;
int v[200010],N,M;
__int64 solve(int x,int y)
{
int k=(M-(x-y+M)%M)%M;
if(v[k]!=-1)
return 1ll*v[k]*N+x;
return inf;
}
int main()
{
int n,m,k,p=0,current=0,i,x,y;
__int64 ans;
memset(v,-1,sizeof(v));
scanf("%d%d%d",&n,&m,&k);
N=2*n,M=2*m;
while(v[current]==-1)//預處理循環節
{
v[current]=p++;
current=(current+N)%M;
}
/*for(i=0;i<N;i++)
printf("%d ",v[i]);
puts("");*/
for(i=0;i<k;i++)
{
scanf("%d%d",&x,&y);
ans=min(min(solve(x,M-y),solve(x,y)),min(solve(N-x,y),solve(N-x,M-y)));
if(ans!=inf)
printf("%I64d\n",ans);
else
puts("-1");
}
return 0;
}
Problem D-Dense Subsequence
Accept: 0 Submit: 0
Time Limit: 2 seconds Memory Limit : 256 megabytes
Problem Description
You are given a string s, consisting of lowercase English letters, and the integer m.
One should choose some symbols from the given string so that any contiguous subsegment of length m has at least one selected symbol. Note that here we choose positions of symbols, not the symbols themselves.
Then one uses the chosen symbols to form a new string. All symbols from the chosen position should be used, but we are allowed to rearrange them in any order.
Formally, we choose a subsequence of indices . The selected sequence must meet the following condition: for every j such that 1 ≤ j ≤ |s| - m + 1, there must be at least one selected index that belongs to the segment [j, j + m - 1], i.e. there should exist a k from 1 to t, such that j ≤ ≤ j + m - 1.
Then we take any permutation p of the selected indices and form a new string.
Find the lexicographically smallest string, that can be obtained using this procedure.
Input
The first line of the input contains a single integer m (1 ≤ m ≤ 100 000).
The second line contains the string s consisting of lowercase English letters. It is guaranteed that this string is non-empty and its length doesn't exceed 100 000. It is also guaranteed that the number m doesn't exceed the length
of the string s.
Output
Print the single line containing the lexicographically smallest string, that can be obtained using the procedure described above.
Sample Input
cbabc
2
abcab
3
bcabcbaccba
Sample Output
aab
aaabb
Hint
In the first sample, one can choose the subsequence {3} and form a string "a".
In the second sample, one can choose the subsequence {1, 2, 4} (symbols on this positions are 'a', 'b' and 'a') and rearrange the chosen symbols to form a string "aab".
Problem Idea
解題思路:
【題意】
給你一個整數m和一個字符串s
現在你要從字符串s中選出一些字符
使得字符串s中任意長度爲m的連續子序列都至少包含這些字符中的一個
要求選出的這些字符排列後字典序最小
【類型】
貪心+亂搞
【分析】
要使得選出的字符排列後字典序最小,有如下幾個策略:
①假設最終選取的一系列字符中字典序最大的爲x,那麼字符串s中所有的y(字典序:y<x)都要選取
顯然 字典序: aaabb < aabb
②在滿足①的條件下,選取的字符x應儘可能少
顯然 字典序: aaabb < aaabbb
【時間複雜度&&優化】
O(26×100000)
題目鏈接→Codeforces Problem 724D Dense Subsequence
Source Code
/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-9
#define LL long long
#define PI acos(-1.0)
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 100005;
const int M = 26;
const int inf = 1000000007;
const int mod = 20160519;
char s[N];
int m,v[M];
bool check(int k)//判斷字符串s中任意長度爲m的連續子序列是否至少包含所選字符中的一個
{
int i,p;
for(i=0;s[i]!='\0'&&s[i]-'a'>k;i++);
if(s[i]=='\0'||i>=m)
return false;
for(p=i+m;s[i]!='\0';i++)
{
if(s[i]-'a'<=k)
p=i+m;
if(i>=p)
break;
}
if(s[i]=='\0')
return true;
return false;
}
int main()
{
int i,k,p,c=0,pos;
scanf("%d",&m);
scanf("%s",s);
for(i=0;s[i]!='\0';i++)
v[s[i]-'a']++;
for(i=0;i<26;i++)
{
if(!v[i])
continue;
if(check(i))
break;
while(v[i]--)
printf("%c",i+'a');
}
//printf("%d\n",i);
//printf("%c\n",i+'a');
k=i;
for(i=0;s[i]!='\0'&&s[i]-'a'>=k;i++)
if(s[i]-'a'==k&&i<m)
pos=i;
if(s[i]=='\0'||i>=m)
i=pos,c++,p=pos+m;
else
p=i+m;
for(;s[i]!='\0';i++)
{
if(s[i]-'a'<k)
p=i+m;
if(s[i]-'a'==k)
pos=i;
if(i>=p)
i=pos,c++,p=pos+m;
}
while(c--)
printf("%c",k+'a');
puts("");
return 0;
}
菜鳥成長記