codeforces round 209 解题报告

来源:互联网 发布:六孔陶笛淘宝 编辑:程序博客网 时间:2024/06/05 18:18

ROUND 209 解题报告

A    Table

关键字:构造

思路:

    答案相当于是否存在一个边界上的格子值为1,且不是拐角。因为如果我们找到了这样一个点,我们可以将这个点,向对边两个点构成的两个矩形染色,这样就能在2的时间内完成。反之,不难证明,只能在4的时间内完成。

时间复杂度:O(nm)

空间复杂度:O(1)

#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>#include<algorithm>using namespace std;int n,m;int num;int main(){cin>>n>>m;int flag=0;for (int i=1;i<=n;i++)for (int j=1;j<=m;j++){int x;cin>>x;if ((i!=1||i!=n)&&(j!=1||j!=m)&&x==1){if (i==1||i==n||j==1||j==m) flag=1;}}if (flag) cout<<2<<endl;else cout<<4<<endl;return 0;}


B    Permutation

关键字:构造

思路:

    我们首先考虑k0时的情况。只要我们在第一个sigma中的每个绝对值内正负情况相同,就能保证k=0 。这个不难构造,只要按12*n的顺序排列即可。考虑其他k的情况,如果k=1,我们交换和 2的位置,此时后面式子的值将会减二。如果k=2,那么在k=1的基础上,交换34的位置即可。。通过这种方式,我们就可以构造出要求的序列了。

时间复杂度:O(n)

空间复杂度:O(1)

#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>#include<algorithm>using namespace std;int main(){<span style="white-space: pre;"></span>int n,k;<span style="white-space: pre;"></span>cin>>n>>k;<span style="white-space: pre;"></span>for (int i=1;i<=n;i++)<span style="white-space: pre;"></span>{<span style="white-space: pre;"></span>if (k>0) printf("%d %d",2*i,2*i-1);<span style="white-space: pre;"></span>else printf("%d %d",2*i-1,2*i);<span style="white-space: pre;"></span>if (i!=n) printf(" ");<span style="white-space: pre;"></span>k--;<span style="white-space: pre;"></span>}<span style="white-space: pre;"></span>printf("\n");<span style="white-space: pre;"></span>return 0;}


C    Prime Number

关键字:STL

思路:

    类似于进制的加法。我们所要求的结果,就是将ai序列的相同项不断合并,直至不能再合并时,x的(Σai-当前最大ai)次方的值。这里我们用一个map就可以轻松完成。从最大的ai开始往0遍历,如果当前值是x的倍数,那就将当前值除以x的值加到前一项中。直到不满足当前值是x的倍数这个条件时结束。

时间复杂度:O(n)

空间复杂度:O(n)

#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>#include<algorithm>#include<map>using namespace std;typedef long long LL;LL pow_mod(LL a,LL i,LL n){if (i==0) return 1%n;LL temp=pow_mod(a,i>>1,n);    temp=temp*temp%n;    if (i&1) temp=(LL) temp*a%n;    return temp;}const LL mod=1e9+7;LL n,x;LL a[110000];map<LL,LL> w;int main(){cin>>n>>x;LL sum=0;w.clear();for (int i=0;i<n;i++){cin>>a[i];w[a[i]]++;sum+=a[i];}int i=a[n-1];while (w[i]%x==0){w[i-1]+=w[i]/x;i--;}if (i<0) i=0;cout<<pow_mod(x,sum-i,mod)<<endl;return 0;}


D    Pair of Numbers

关键字:暴力

思路:

    我们从j=1开始枚举aj的值。然后分别从两边扩展,直到当前数不是aj的倍数为止。这里加一个小优化就可以过:如果当前最右边扩展到r,那么下次jr+1开始,不影响程序的正确性。

时间复杂度:O(n)

空间复杂度:O(n)

#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>#include<algorithm>using namespace std;int a[400000],w[400000];int main(){int n;cin>>n;for (int i=0;i<n;i++)cin>>a[i];int maxx=0,num=0;for (int i=0;i<n;){int r,l;r=l=i;while (l&&a[l-1]%a[i]==0) l--;while (r<n-1&&a[r+1]%a[i]==0) r++;i=r+1;r-=l;if (r>maxx) num=0,maxx=r;    if (r==maxx) w[num++]=l+1;}cout<<num<<" "<<maxx<<endl;for (int i=0;i<num;i++){cout<<w[i];if (i!=n) printf(" ");else printf("\n");}return 0;}


E    Neatness

关键字:构造

思路:

    题目只要求找出解,并没有要求最短,所以此题主要难点在于构造。我们可以用最“蠢”的方法,但是保证其最大的正确性:dfs。首先需要dfs(x0,y0)Dfs时,需要判断四个方向,是否有未遍历过且可达的点,我们再递归去遍历该点。另外一个策略就是,每每第一次到一个点时,将其灯打开,最后一次回到这个点时,将灯关闭,这样就保证了策略的正确性。

时间复杂度:O(n^2)

空间复杂度:O(n^2) 

 

 

#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>#include<algorithm>using namespace std;int n,x,y;int a[600][600],pp[600][600],sum=0;char q[4000000];int ans=0;const int D[4][2]={{0,1},{0,-1},{1,0},{-1,0}};const char c[4]={'R','L','D','U'};bool check(int x,int y,int d){for (x+=D[d][0],y+=D[d][1];x>=1&&x<=n&&y>=1&&y<=n;x+=D[d][0],y+=D[d][1])if (a[x][y]) return !pp[x][y];return 0;}void dfs(int x,int y){pp[x][y]=1;if (!a[x][y]){ a[x][y]=1; sum++; ans++; q[ans]='1';}for (int i=0;i<4;i++) if (check(x,y,i)){ans++;q[ans]=c[i];dfs(x+D[i][0],y+D[i][1]);ans++;q[ans]=c[i^1];}a[x][y]=0;sum--;ans++;q[ans]='2';}int main(){cin>>n>>x>>y;for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)    scanf("%d",&a[i][j]),sum+=a[i][j];dfs(x,y);if (sum){cout<<"NO"<<endl;return 0;}cout<<"YES"<<endl;for (int i=1;i<=ans;i++)    printf("%c",q[i]);cout<<endl;return 0;}

 

 

 

 

 

0 0