• Codeforces #639 (div 1) 做题记录


    随便写点题,按时间倒序随便刷刷

    A.

    如果有两个相等可以列等式(i+a_{i mod n}=j+a_{j mod n})

    令(i=k_1n+p,j=k_2n+q),则有(k_1n+p+a_p=k_2n+q+a_q)

    即存在(p,q),(p+a_p=q+a_q)在(mod n)意义下相等,这个直接判就行了

     1 #include<bits/stdc++.h>
     2 #define maxn 200005
     3 using namespace std;
     4 int T,n;
     5 int a[maxn];
     6 int main()
     7 {
     8     scanf("%d",&T);
     9     while(T--)
    10     {
    11         scanf("%d",&n);
    12         for(int i=0;i<n;++i)scanf("%d",&a[i]);
    13         for(int i=0;i<n;++i)a[i]=((a[i]+i)%n+n)%n;
    14         sort(a,a+n);
    15         bool fl=0;
    16         for(int i=1;i<n;++i)if(a[i]==a[i-1])fl=1;
    17         if(fl)puts("NO");
    18         else puts("YES");
    19     }
    20 }
    View Code

     B.

    考虑同一行/同一列不能出现两个黑块中间有白块的情况:

    如果有这样的情况,那么如果这两个黑块都是N磁铁可达的,那么在这行/列的其他位置必然有一个S磁铁,这样随便操作一下N磁铁就进白块了

    所以每行/列最多一个连通块

    如果是(0)个,那么需要单独考虑(因为每行每列都至少要有一个S,所以必须找出一个位置放S,而这样的位置必须是空行和空列的交点)

    其他情况显然合法

    最小个数就是每个连通块一个N磁铁

     1 #include<bits/stdc++.h>
     2 #define maxn 1005 
     3 using namespace std;
     4 int n,m;
     5 char a[maxn][maxn];
     6 bool vis[maxn][maxn];
     7 int id[maxn][maxn],cnt;
     8 void dfs(int x,int y)
     9 {
    10     if(a[x][y]!='#')return;
    11     if(vis[x][y])return;
    12     vis[x][y]=1;
    13     id[x][y]=cnt;
    14     dfs(x+1,y);dfs(x-1,y);dfs(x,y+1);dfs(x,y-1);
    15 }
    16 int main()
    17 {
    18     scanf("%d%d",&n,&m);
    19     for(int i=1;i<=n;++i)scanf("%s",a[i]+1); 
    20     for(int i=1;i<=n;++i)
    21         for(int j=1;j<=m;++j)if(a[i][j]=='#'&&(!vis[i][j]))
    22         {
    23             ++cnt;
    24             dfs(i,j);
    25         }
    26     bool yes=1,y1=0,y2=0;
    27     for(int i=1;i<=n;++i)
    28     {
    29         int lst=0;
    30         for(int j=1;j<=m;++j)if(a[i][j]=='#')
    31         {
    32             if(!lst)lst=j;
    33             else
    34             {
    35                 if(j==lst+1)lst=j;
    36                 else yes=0;
    37             }
    38         }
    39         if(!lst)y1=1;
    40     }
    41     for(int j=1;j<=m;++j)
    42     {
    43         int lst=0;
    44         for(int i=1;i<=n;++i)if(id[i][j])
    45         {
    46             if(!lst)lst=i;
    47             else
    48             {
    49                 if(i==lst+1)lst=i;
    50                 else yes=0;
    51             }
    52         }
    53         if(!lst)y2=1;
    54     }
    55     if(y1!=y2)yes=0;
    56     if(!yes)puts("-1");
    57     else printf("%d
    ",cnt);
    58 }
    View Code

     C.

    先判有没有解

    显然最松的约束是所有都是存在的情况,这个只要拓扑排序判环就行了

    然后考虑找解

    还是按照上面的图建图

    因为每个变量的出现先后顺序是定的,所以如果某个变量(x_i)被定下来了,那么显然编号大于(i)的并且又和(i)存在大小关系的变量一定是存在

    那么我们按编号从小往大考虑,如果一个变量没和之前的变量存在大小关系,那直接贪心的选成任意最优,否则是存在

    这个存不存在大小关系就在图上dfs一下前驱后继标记一下就行了

     1 #include<bits/stdc++.h>
     2 #define maxn 200005
     3 using namespace std;
     4 int n,m;
     5 vector<int> g[maxn],g2[maxn];
     6 int d[maxn];
     7 char Ans[maxn];
     8 bool vis[maxn],vis2[maxn];
     9 void dfs(int u)
    10 {
    11     if(vis[u])return;
    12     vis[u]=1;
    13     for(int v:g[u])dfs(v);
    14 }
    15 void dfs2(int u)
    16 {
    17     if(vis2[u])return;
    18     vis2[u]=1;
    19     for(int v:g2[u])dfs2(v);
    20 }
    21 int main()
    22 {
    23     scanf("%d%d",&n,&m);
    24     for(int i=1;i<=m;++i)
    25     {
    26         int u,v;
    27         scanf("%d%d",&u,&v);
    28         g[u].push_back(v);
    29         g2[v].push_back(u);
    30         d[v]++; 
    31     }
    32     queue<int> q;
    33     for(int i=1;i<=n;++i)if(!d[i])q.push(i);
    34     int has=0;
    35     while(!q.empty())
    36     {
    37         int u=q.front();q.pop();
    38         ++has;
    39         for(int v:g[u])
    40         {
    41             --d[v];
    42             if(!d[v])q.push(v);
    43         }
    44     }
    45     if(has!=n)puts("-1");
    46     else
    47     {
    48         int ans=0;
    49         for(int i=1;i<=n;++i)
    50         {
    51             if(vis[i]||vis2[i])Ans[i]='E';
    52             else Ans[i]='A',++ans;
    53             dfs(i);
    54             dfs2(i);
    55         }
    56         printf("%d
    ",ans);
    57         printf("%s
    ",Ans+1);
    58     }
    59 }
    View Code

     D.

    一开始想到偏导上去了,但发现并不能处理(b_i leq a_i)的限制条件

    考虑计算每次的增量: 在第(i)种从(b_i)到(b_{i+1})时,增量为(a_i-3b_i^2-3b_i-1)

    有一个暴力的贪心做法是每次用堆维护最大的增量贪(k)次

    但这个(k)很大

    发现增量是单调递减的,我们二分最小增量(x),对每种再用一次二分求出(b_i)

    这样剩下的零头不会超过(O(n)),按上面用堆贪一下就行了

     1 #include<bits/stdc++.h>
     2 #define maxn 100005
     3 #define ll long long 
     4 #define mp(a,b) make_pair(a,b)
     5 using namespace std;
     6 int n;
     7 ll k,a[maxn],b[maxn];
     8 ll calc(ll t)
     9 {
    10     ll tot=0;
    11     for(int i=1;i<=n;++i)
    12     {
    13         ll L=0,R=a[i],ans=0;
    14         while(L<=R)
    15         {
    16             ll M=(L+R)/2;
    17             if(a[i]-M*M*3-M*3-1>=t)ans=M,L=M+1;
    18             else R=M-1;
    19         }
    20         b[i]=ans;
    21         tot+=ans;
    22     }
    23     return tot;
    24 }
    25 int main()
    26 {
    27     scanf("%d%lld",&n,&k);
    28     for(int i=1;i<=n;++i)scanf("%lld",&a[i]);
    29     ll L=-(ll)4e18,R=(ll)2e9,ans=R;
    30     while(L<=R)
    31     {
    32         ll M=(L+R)/2;
    33         if(calc(M)<=k)ans=M,R=M-1;
    34         else L=M+1;
    35     }
    36     calc(ans);
    37     for(int i=1;i<=n;++i)k-=b[i];
    38     priority_queue< pair<ll,int> > pq;
    39     for(int i=1;i<=n;++i)if(b[i]<a[i])pq.push(mp(a[i]-b[i]*b[i]*3-b[i]*3-1,i));
    40     for(int i=1;i<=k;++i)
    41     {
    42         int u=pq.top().second;pq.pop();
    43         ++b[u];
    44         if(b[u]<a[u])pq.push(mp(a[u]-b[u]*b[u]*3-b[u]*3-1,u));
    45     }
    46     for(int i=1;i<=n;++i)printf("%lld ",b[i]);
    47 }
    View Code
  • 相关阅读:
    Vivian's Problem UVA
    Prime k-tuple UVA
    M
    Make a Crystal UVA
    Cryptography Reloaded UVALive
    Gauss Prime UVA
    Discrete Square Roots UVALive
    The Bells are Ringing UVALive
    Huge Mods UVA
    指数循环节
  • 原文地址:https://www.cnblogs.com/uuzlove/p/12863639.html
Copyright © 2020-2023  润新知