A.Do Not Be Distracted!
- 解题思路
利用容器记录之前出现过的字母,我们只需要遍历字符串判断当前的字符有没有在之前出现过(注意是不连续的出现)。
- AC代码
/**
*@filename:A_Do_Not_Be_Distracted_
*@author: pursuit
*@created: 2021-05-05 22:35
**/
using namespace std;
typedef long long ll;
const int maxn = 100000 + 5;
const int mod = 1e9+7;
int t,n;
string s;
map<char,int> p;
void solve(){
p.clear();
char pre=s[0];
p[pre]++;
bool flag=false;
for(int i=1;i<n;i++){
if(s[i]!=pre){
if(p.find(s[i])!=p.end()){
flag=true;
break;
}
else{
pre=s[i];
p[s[i]]++;
}
}
}
if(!flag){
cout<<"YES"<<endl;
}
else{
cout<<"NO"<<endl;
}
}
int main(){
cin>>t;
while(t--){
cin>>n;
cin>>s;
solve();
}
return 0;
}
B.Ordinary Numbers
- 解题思路
此题需要我们知道1~n以内的所有普通数,即位数上的数字都相等,那么这种数有什么规律呢?,
,
。我们发现,实际上只需要起始从
构成的相等数开始,再每次加上这个数即可。需要注意的就是进位。
- AC代码
/**
*@filename:B_Ordinary_Numbers
*@author: pursuit
*@created: 2021-05-05 22:39
**/
using namespace std;
typedef long long ll;
const int maxn = 100000 + 5;
const int mod = 1e9+7;
int t,n;
bool check(int x){
string temp=to_string(x);
for(int i=0;i<temp.size()-1;i++){
if(temp[i]!=temp[i+1])return false;
}
return true;
}
void solve(){
int ans=0;
int k=1,temp=1;
for(int i=temp;i<=n;i+=temp){
if(check(i))ans++;
else{
//不行,说明已经进位,我们需要让temp变为当前长度的1。
temp=temp*10+1;
i=0;
}
}
cout<<ans<<endl;
}
int main(){
cin>>t;
while(t--){
cin>>n;
solve();
}
return 0;
}
C. Not Adjacent Matrix
- 解题思路
构造问题,我们是要让相邻单元格的差值不为,所以我们自然能想到用奇数和奇数相邻,偶数和偶数相邻,所以我们可以先从小到大填充所有的奇数,填完奇数之后再从小到大填充完所有的偶数。这种做法除了
不满足情况,其他的均可满足。因为除
之外奇数和偶数相邻的那部分单元格差值不为
。
- AC代码
/**
*@filename:C_Not_Adjacent_Matrix
*@author: pursuit
*@created: 2021-05-05 22:49
**/
using namespace std;
typedef long long ll;
const int maxn = 100 + 5;
const int mod = 1e9+7;
int t,n;
int a[maxn][maxn];
void solve(){
if(n==2)cout<<-1<<endl;
else{
int odd=1,even=2;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(odd>n*n){
a[i][j]=even;
even+=2;
}
else{
a[i][j]=odd;
odd+=2;
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<a[i][j]<<" ";
}
cout<<endl;
}
}
}
int main(){
cin>>t;
while(t--){
cin>>n;
solve();
}
return 0;
}
D. Same Differences
- 解题思路
这道题其实特别简单,我们需要将给定的公式变形,即,变形得到
。这样题目实际上就解决了。利用
容器记录
出现的次数,遍历数组的时候累加之前出现的
的次数即可。需要注意的就是统计用long long类型,会爆int。
- AC代码
/**
*@filename:D_Same_Differences
*@author: pursuit
*@created: 2021-05-05 22:57
**/
using namespace std;
typedef long long ll;
const int maxn = 200000 + 5;
const int mod = 1e9+7;
int t,n,a[maxn];
map<int,int> p;
void solve(){
ll ans=0;
//aj-j=ai-i;
for(int i=1;i<=n;i++){
ans+=p[a[i]-i];
p[a[i]-i]++;
}
cout<<ans<<endl;
}
int main(){
cin>>t;
while(t--){
cin>>n;
p.clear();
for(int i=1;i<=n;i++)cin>>a[i];
solve();
}
return 0;
}
E. Arranging The Sheep
- 解题思路
根据贪心原则,我们总是想往中间靠,那么我们则需要找到最中间的即可,所以我们可以将这些
字符的下标存储起来,需要处理的一个细节就是,我们需要将连续的
看成是一个点,因为它们转移的消耗是一样的。处理完之后,开始判断选取哪个中点,取最小值即可。
- AC代码
/**
*@filename:E_Arranging_The_Sheep
*@author: pursuit
*@created: 2021-05-05 23:16
**/
using namespace std;
typedef long long ll;
const int maxn = 1000000 + 5;
const int mod = 1e9+7;
int t,n;
string s;
void solve(){
vector<int> pos;
//我们可以认为连续的就是同一个点,这样方便处理。
int idx=1;
for(int i=0;i<n;i++){
if(s[i]=='*')pos.push_back(idx);
else idx++;
}
if(pos.empty()){
//说明为空。
cout<<0<<endl;
return;
}
//选择中间位置进行处理。
int idx1=pos.size()/2,idx2=(pos.size()-1)/2;
ll cnt1=0,cnt2=0;
/* for(int i=0;i<pos.size();i++){
cout<<pos[i]<<" ";
} */
/* cout<<endl; */
for(int i=0;i<pos.size();i++){
cnt1+=abs(pos[idx1]-pos[i]);
cnt2+=abs(pos[idx2]-pos[i]);
/* cout<<cnt1<<" "<<cnt2<<endl; */
}
cout<<min(cnt1,cnt2)<<endl;
}
int main(){
cin>>t;
while(t--){
cin>>n>>s;
solve();
}
return 0;
}
F1. Guess the K-th Zero (Easy version)
- 题目大意
给定一个数组的长度,我们需要利用不超过
次的查询来找到第
个
的位置。在简单版本中,我们只需要找一个
。
- 解题思路
对于这种问题,我们应该要想到二分查找,这样我们才能保证在不超过次的查询来找到第
个
的位置,因为
。那么二分的话我们需要维护一个可行区间
,每次查询
,而返回的结果
是该区间中
的个数,那么自然该区间中
的个数为
,我们用这个与
比较,判断我们查询的
在哪个区间即可,需要注意的是,如果是在右边,那么我们需要更新
,因为我们在意的是相对位置,而左区间已经有
个
了,那么终止的时候也就是找到了第
个
的位置,即
。
- AC代码
/**
*@filename:F1_Guess_the_K_th_Zero_Easy_version_
*@author: pursuit
*@created: 2021-05-06 00:06
**/
using namespace std;
typedef long long ll;
const int maxn = 100000 + 5;
const int mod = 1e9+7;
int t,n,k;
//二分查找。
void solve(){
int T=20;//查找次数最多20次。
int l=1,r=n;
while(T--){
int mid=(l+r)>>1;//我们每次二分查询即可得到所在区间。
cout<<"?"<<" "<<l<<" "<<mid<<endl;
cout.flush();
int res;
cin>>res;//这个即返回的是[l,mid]这段区间的1的数量,那么0的数量自然易得。
int cnt=mid-l+1-res;
if(cnt<k){
//说明第k个0在右边。
k-=cnt;
l=mid+1;
}
else{
//说明第k个0在左边。
r=mid;
}
if(l==r){
cout<<"! "<<l<<endl;
break;
}
}
}
int main(){
cin>>n>>t;
while(t--){
cin>>k;
solve();
}
return 0;
}
F2. Guess the K-th Zero (Hard version)
- 解题思路
目前还不会,待补。
G. To Go Or Not To Go?
- 解题思路
我们知道若为
,则说明不准通行,否则其他的都可以正常移动,每次移动的消耗为
。特殊的是若该点权值大于
,说明可以使用传送器到有传送器的地方,消耗为
。由于可以任意传送,所以其实使用传送器只会使用一次。那么我们就可以先计算出不使用传送器从
出发和从
出发到达各点的最短路径,得到了这些之后,我们就可以枚举使用的传送门(记住,这里的传送门有两处,一处是从起点到达的
,一处是从
传送到达的
)取最优了,即维护
和
的最小值,然后再与不使用传送门直接到达
的
取最小值即可。
- AC代码
/**
*@filename:G_To_Go_Or_Not_To_Go_
*@author: pursuit
*@created: 2021-05-06 21:45
**/
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 2000 + 5;
const int mod = 1e9+7;
const ll inf = 0x3f3f3f3f3f3f3f;
int n,m,w;
ll dist1[maxn][maxn],dist2[maxn][maxn];//dist1[i][j]表示(1,1)到(i,j)的最短路径,dist2[i][j]表示(n,m)到(i,j)的最短路径。
int g[maxn][maxn];//图。
int go[4][2]={0,1,1,0,0,-1,-1,0};//行走路径。
void bfs(pii st,ll dist[maxn][maxn]){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
dist[i][j]=inf;//初始化。
}
}
queue<pii> q;
dist[st.x][st.y]=0;
pii head,temp;
q.push(st);
while(!q.empty()){
head = q.front();
q.pop();
for(int i=0;i<4;i++){
temp.x=head.x+go[i][0],temp.y=head.y+go[i][1];
if(temp.x>=1&&temp.x<=n&&temp.y>=1&&temp.y<=m&&g[temp.x][temp.y]!=-1&&dist[temp.x][temp.y]>dist[head.x][head.y]+w){
dist[temp.x][temp.y]=dist[head.x][head.y]+w;
q.push(temp);
}
}
}
}
void solve(){
bfs({1,1},dist1);
bfs({n,m},dist2);
ll minn1=inf,minn2=inf;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
//穿插使用传送门,优化最小值。
if(g[i][j]<=0)continue;
minn1=min(minn1,dist1[i][j]+g[i][j]);
minn2=min(minn2,dist2[i][j]+g[i][j]);
//cout<<minn1<<" "<<minn2<<endl;
}
}
ll ans=min(minn1+minn2,dist1[n][m]);
if(ans>=inf)ans=-1;
printf("%lld\n",ans);//注意是lld
}
int main(){
scanf("%d%d%d",&n,&m,&w);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&g[i][j]);
}
}
solve();
return 0;
}