https://codeforces.com/contest/1333
A. Little Artem
- 題目大意:構造一個的矩陣:1、只有黑白兩種顏色;2、要滿足(B表示黑色單元格的個數,並且這些單元格周圍至少有一個白色單元格,W類似)
- 思路:在左上角的一個單元格塗上白色(與它相鄰的單元格剛好只有兩個),其他全塗黑色
#include <iostream>
#include <stdio.h>
#include <algorithm>
//#define int long long
using namespace std;
const int INF=0x3f3f3f3f;
const int manx=1e5+10;
void black(int n)
{
for(int i=0;i<n;i++)
printf("B");
printf("\n");
}
void white(int n)
{
for(int i=0;i<n;i++)
printf("W");
}
int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
white(1);
black(m-1);
for(int i=1;i<n;i++)
black(m);
}
return 0;
}
B. Kind Anton
- 題目大意:給定長度均爲n的兩個數列,只能是中的一個數,問是否能執行若干次操作使數列與數列相等
- 因爲只能將前面的數累加到後面,所以當時,只用看到中有沒有1;時,就看前面有沒有-1(有的人想着想着就忘了i<j :)……
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int manx=1e5+10;
int main()
{
int t,n,a[manx],b;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int f_1=0,f1=0,ans=1;
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
for(int i=0;i<n;i++)
{
scanf("%d",&b);
if(ans&&a[i]>b&&f_1==0)
ans=0;
if(ans&&a[i]<b&&f1==0)
ans=0;
if(a[i]==-1)
f_1=1;
else if(a[i]==1)
f1=1;
}
if(ans)
printf("YES\n");
else printf("NO\n");
}
return 0;
}
C. Eugene and an array
- 題目大意:給定一個長度爲n的序列,定義good array 爲不含有和爲0的連續子序列,問這個序列中有多少個good array
- 思路:我們可以求一次前綴和,如果某兩個前綴和相等,就說明這段子序列和爲0。因爲我們找的這些子序列中不能含有某段和爲0的連續子序列,所以,我們可以記錄這些序列的左端點的最大值爲p,處理到第i位時,以i結尾的good array 個數就等於
//爲了避免討論不存在相等前綴和和其他特殊情況情況,所以在序列前面加了一個0
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <map>
#define int long long
using namespace std;
const int INF=0x3f3f3f3f;
const int manx=2e5+10;
map<int,int>mp;
signed main()
{
int n,a,ans=0,psum=0,p=0;
scanf("%lld",&n);
mp[0]=1;
for(int i=2;i<=n+1;i++)
{
scanf("%lld",&a);
psum+=a;
p=max(p,mp[psum]);
ans+=i-p-1;
mp[psum]=i;
}
printf("%lld",ans);
return 0;
}
D. Challenges in school №41
- 題目大意:n個人站成一排,要麼朝向左邊,要麼朝向右邊。如果兩個人相鄰且 looking at each other ,那麼他們兩個人可以在1s以內轉向和原來相反的方向。問:是否存在一種步驟,使他們在k秒後不存在相鄰且對視的情況。(多解)
- 思路:在1s內,可能不止一對人滿足可以同時轉向另一面的條件,但是他們之間是互不影響的,比如“RLRL”中第三個人肯定是和第四個人同時轉向,而不會是1、2兩個人轉向後,2、3兩個人也能滿足同時轉向的條件(感覺說不太清楚地樣子)。所以我們可以先處理出最短的時間,即在每1s內能夠轉向的都轉向,一直重複這個步驟,直到不存在相鄰且對視的情況(ps:題目有保證說轉向次數不會超過n2次,且n<3e3)
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <vector>
//#define int long long
using namespace std;
const int INF=0x3f3f3f3f;
const int manx=3e3+10;
char str[manx];
int a[manx][manx],n,k,cou=0,sum=0;
int main()
{
scanf("%d%d",&n,&k);
scanf("%s",str+1);
for(int i=0;i<=n;i++)
a[i][0]=0;
while(1)
{
for(int i=1;i<n;i++)
{
if(str[i]=='R'&&str[i+1]=='L')
{
a[cou][0]++;
a[cou][a[cou][0]]=i;
str[i]='L';
str[i+1]='R';
i++;
}
}
if(!a[cou][0])break;
sum+=a[cou][0];
cou++;
}
if(sum<k||cou>k)
{
printf("-1\n");
return 0;
}
for(int i=0;i<cou;)
{
if(cou-i==k)
{
printf("%d",a[i][0]);
for(int j=1;j<=a[i][0];j++)
printf(" %d",a[i][j]);
printf("\n");
i++;
k--;
}
else
{
printf("1 %d\n",a[i][a[i][0]]);
a[i][0]--;
if(!a[i][0])
i++;
k--;
}
}
return 0;
}
F. Kate and imperfection
- 題目大意:一個包含n個數:1、2、3……n的集合S,(一個集合中存在最大的值)求S的k個元素的子集中,最小的,k=2、3、4……n.
- 思路:首先k=n時,最小的很容易求出(因爲n個元素的子集只有一個);要使k=n-1時,最小,就應該刪去n個元素中產生的數。因爲是連續的n個數,所以每個數能產生的最大__gcd()值就是它的最大因子(不含本身),將這些最大因子排序,逐個輸出就可以了
- O(nlogn):也可以用素數打表裏面的線性篩,因爲線性篩裏面每個數只被它的最小因子篩選一次,所以就能夠很容易得到它的最大因子
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <map>
//#define int long long
using namespace std;
const int INF=0x3f3f3f3f;
const int manx=5e5+10;
int a[manx];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int flag=1;
for(int j=2;j*j<=n;j++)
{
if(i%j==0)
{
flag=i/j;
break;
}
}
a[i]=flag;
}
sort(a+1,a+n+1);
for(int i=2;i<=n;i++)
printf("%d ",a[i]);
printf("\n");
return 0;
}