Codeforces Round #596 Div1 A~E题解

I'm good food ah

A

The meaning of problems:
the definition of a binary number to p- 2 ^ kp, gives the n and p, n seeking to represent a binary number with a minimum number of p-
1 <= n <= 10 ^ 9, -1000 <= p <= 1000

Solution:
I guess the conclusion that the answer will not be great
n can be expressed in the form kp + s, the enumeration k, determine (n-kp) if you can use the power of the k 2 constitutes
draw at Figure can be found, if you can constitute, then digit satisfy (n-kp) of <= k <= the n--KP
(equivalent to a point on a binary tree into two)
prove the answer will not be great:
first (n-kp) up to the number of bits 30
① P> = 0
obviously when k exceeds 30, and if not then not satisfied after
②p <0
then n-kp is clearly greater than equal to k

code

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
using namespace std;

long long n,s;
int p,i,j,k,l;

bool pd(long long t)
{
    long long T=t;
    int sum=0;
    
    while (T)
    {
        sum+=T&1;
        T>>=1;
    }
    
    if (s>=sum && s<=t)
    return 1;
    else
    return 0;
}

int main()
{
//  freopen("a.in","r",stdin);
    
    scanf("%I64d%d",&n,&p);
    
    while (!pd(n))
    {
        n-=p;
        ++s;
        
        if (n<0 ||s>100)
        break;
    }
    
    if (n>=0 && pd(n))
    printf("%I64d\n",s);
    else
    printf("-1\n");
}

B

The meaning of problems:
given number of n and k, find (i, j) number (i <j), such that X = AJ ^ * AI K
n <^ 5,2 = 10 <= K <= 100

Solution:
can be expressed as a power of x k, the index means that the product after each prime factorisation% k = 0
i.e. (ai + aj index p in the exponent p)% k = 0, the i or negative index j taking into seeking ai (i, j) and an equal number of prime factors aj index
can be sorted out, according to discuss large prime numbers k

code

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
using namespace std;

int a[200001];
int p[200001][66];
int P[317];
int c[200001];
int N,n,K,i,j,k,l,s,len,ls,s1,s2;
long long ans;
bool bz;

bool cmp(int a,int b)
{
    int i;
    
    fo(i,1,65)
    if (p[a][i]<p[b][i])
    return 1;
    else
    if (p[a][i]>p[b][i])
    return 0;
    
    return 0;
}

bool pd(int t)
{
    int i;
    
    fo(i,1,65)
    if (p[a[t]][i]!=p[a[t+1]][i])
    return 0;
    return 1;
}

bool Cmp(int x,int y)
{
    return p[x][0]<p[y][0];
}

int main()
{
//  freopen("b.in","r",stdin);
    
    fo(i,2,316)
    {
        k=1;
        
        fo(j,2,floor(sqrt(i)))
        if (!(i%j))
        {
            k=0;
            break;
        }
        
        if (k)
        P[++len]=i;
    }
    
    scanf("%d%d",&n,&K);
    fo(i,1,n)
    {
        scanf("%d",&l);
        fo(j,1,len)
        if (!(l%P[j]))
        {
            while (!(l%P[j]))
            {
                l/=P[j];
                ++p[i][j];
            }
            p[i][j]%=K;
            p[i+n][j]=(K-p[i][j])%K;
        }
        
        if (l>1)
        {
            p[i][0]=l;
            p[i+n][0]=l;
        }
    }
    
    N=n+n;
    fo(i,1,N)
    a[i]=i;
    
//  fo(i,1,N)
//  {
//      fo(j,0,5)
//      cout<<p[i][j]<<" ";
//      cout<<endl;
//  }
    
    sort(a+1,a+N+1,cmp);
    
//  fo(i,1,N)
//  cout<<a[i]<<endl;
//  fo(i,1,N)
//  {
//      fo(j,0,5)
//      cout<<p[a[i]][j]<<" ";
//      cout<<endl;
//  }
    
    ls=1;
    fo(i,1,N)
    if (i==N || !pd(i))
    {
        l=0;
        fo(j,ls,i)
        c[++l]=a[j];
        
        sort(c+1,c+l+1,Cmp);
        
        if (K>=3)
        {
            s1=0;s2=0;
            
            fo(j,1,l)
            if (!p[c[j]][0])
            {
                if (c[j]<=n)
                ++s1; else ++s2;
            }
            
//          fo(j,1,l)
//          if (c[j]<=n)
//          cout<<c[j]<<" ";
//          else
//          cout<<-(c[j]-n)<<" ";
//          cout<<endl;
//          cout<<" "<<s1*s2<<" "<<s1<<" "<<s2<<endl;
            
            ans+=(long long)s1*s2;
        }
        else
        {
            s1=0;s2=0;
            fo(j,1,l)
            {
                if (j==1 || p[c[j]][0]==p[c[j-1]][0])
                {
                    if (c[j]<=n)
                    ++s1; else ++s2;
                }
                else
                {
                    ans+=(long long)s1*s2;
                    
                    s1=0;s2=0;
                    if (c[j]<=n)
                    ++s1; else ++s2;
                }
            }
            ans+=(long long)s1*s2;
        }
        
        ls=i+1;
    }
    
    if (K==2)
    {
        fo(i,1,n)
        {
            fo(j,1,65)
            if ((p[i][j]*2%K))
            break;
            
            if (j>65)
            --ans;
        }
    }
    else
    {
        fo(i,1,n)
        if (!p[i][0])
        {
            fo(j,1,65)
            if ((p[i][j]*2%K))
            break;
            
            if (j>65)
            --ans;
        }
    }
    
    printf("%I64d\n",ans/2);
}

C

The meaning of problems:
analysis of n * m grid graph, each grid514Or is empty the stone
from (1,1) to the start (n, m) is moved (only the right / lower), will each move one line / one stone right / pushdown a grid, can not square stone Release FIG outer grid
logarithmically program

answer:
Almost on the title cut of sb
There are several legitimate path to a turning point, can be found at each turn stones on the go in the direction did not pushed through
so only need to consider the future direction of the current number of stone can be transferred, with the prefix and optimization

code

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define mod 1000000007
using namespace std;

bool a[2002][2002];
int s1[2002][2002];
int s2[2002][2002];
int f[2002][2002][2];
int g[2002][2002][2];
int n,m,i,j,k,l;
char ch;

int main()
{
//  freopen("c.in","r",stdin);
    
    scanf("%d%d",&n,&m);
    fo(i,1,n)
    {
        fo(j,1,m)
        {
            ch=getchar();
            while (ch!='.' && ch!='R')
            ch=getchar();
            
            a[i][j]=ch=='R';
        }
    }
    
    if (a[n][m])
    {
        printf("0\n");
        return 0;
    }
    if (n==1 && m==1)
    {
        printf("1\n");
        return 0;
    }
    
    fd(i,n,1)
    {
        fd(j,m,1)
        {
            s1[i][j]=s1[i][j+1]+a[i][j];
            s2[i][j]=s2[i+1][j]+a[i][j];
        }
    }
    
    f[1][1][0]=1;
    f[1][1][1]=1;
    fo(i,1,n)
    {
        fo(j,1,m)
        {
            if (i>1 || j>1)
            {
                f[i][j][0]=g[i][j][0];
                f[i][j][1]=g[i][j][1];
            }
            
            fo(k,0,1)
            if (f[i][j][k])
            {
                if (!k)
                {
                    g[i][j][k^1]=(g[i][j][k^1]+f[i][j][k])%mod;
                    g[i][m-s1[i][j+1]+1][k^1]=(g[i][m-s1[i][j+1]+1][k^1]-f[i][j][k])%mod;
                }
                else
                {
                    g[i][j][k^1]=(g[i][j][k^1]+f[i][j][k])%mod;
                    g[n-s2[i+1][j]+1][j][k^1]=(g[n-s2[i+1][j]+1][j][k^1]-f[i][j][k])%mod;
                }
            }
            
            g[i][j+1][1]=(g[i][j+1][1]+g[i][j][1])%mod;
            g[i+1][j][0]=(g[i+1][j][0]+g[i][j][0])%mod;
        }
    }
    
    printf("%d\n",((f[n][m][0]+f[n][m][1])%mod+mod)%mod);
}

D

The meaning of problems:
the strand operation several times, each operation to select a point, this point is set to the father of its father's father
seeking operation such that the minimum chain can become a given tree, and the chain is given the initial number of points and number of each operation

Solution:
very wonderful structure problem
initially wanted each point to the youngest sibling in the depth of the point,But hung up
Consider the tree becomes a chain, one operation is essentially the father of a point to a sibling that's
due to the depth of the tree each operate up to +1, the lower limit for the number of operations (n- depth)
to find the tree longest chain, each to move a point v on the longest chain u brothers, the longest chain down more u
each depth +1, so this is just the number of operations (N- depth), i.e. for the best

code

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
using namespace std;

int a[100001][2];
int ls[100001];
int fa[100001];
int nx[100001];
int Ans[100001];
bool bz[100001];
int d[100001];
int n,i,j,k,l,len,ans,tot,tot2,mx,mx2,h,t;

void New(int x,int y)
{
    ++len;
    a[len][0]=y;
    a[len][1]=ls[x];
    ls[x]=len;
}

void dfs(int t,int d)
{
    int i;
    
    if (d>mx)
    mx=d,mx2=t;
    
    for (i=ls[t]; i; i=a[i][1])
    fa[a[i][0]]=t,dfs(a[i][0],d+1);
}

int main()
{
//  freopen("d.in","r",stdin);
    
    scanf("%d",&n);
    fo(i,2,n)
    {
        scanf("%d",&fa[i]);++fa[i];
        New(fa[i],i);
    }
    
    dfs(1,1);
    
    while (mx2)
    {
        bz[mx2]=1;
        
        nx[fa[mx2]]=mx2;
        mx2=fa[mx2];
    }
    fo(j,1,n)
    if (bz[j])
    {
        for (i=ls[j]; i; i=a[i][1])
        if (!bz[a[i][0]])
        d[++t]=a[i][0];
    }
    
    while (h<t)
    {
        ++h;
        j=nx[fa[d[h]]];
        
        for (i=ls[d[h]]; i; i=a[i][1])
        d[++t]=a[i][0];
        
        fa[j]=d[h];
        nx[fa[d[h]]]=d[h];
        nx[d[h]]=j;
        
        Ans[++tot]=j;
    }
    
    for (i=1; i; i=nx[i])
    printf("%d ",i-1);
    printf("\n");
    printf("%d\n",tot);
    fd(i,tot,1)
    printf("%d ",Ans[i]-1);
}

E

The meaning of problems:
given a number k and the number n (k can not divisible), each time two numbers can be combined, in addition to the combined values k does not divide up until the
required combined into one kind of the number n 1 of Scheme
n <= 16, k <= 2000, Σai <= 2000

Solution to a problem:
O (the n-3 ^ * 2000) is obviouslyI had not
Can be found, each merger was finally can be expressed as Σai * k ^ bi, where bi <0
prove each Σai * k ^ bi = 1 is able to correspond to a legitimate program:
①n = 1
then only a1 = 1 if established
(where a1> 1 does not exist)
②n>. 1
is provided smallest sequence bi is B, then there must be at least two bi = B
proof:
If there is only one, then
Σai * k ^ bi = . 1
Σai * k ^ (BI-B) = k ^ (- B)
when bi> B, the product will be a multiple of k, and k is a multiple of the right also
if there is only one bi = B, and ai% k ≠ 0, ranging from about actual inevitably vary in significance die k

So each time the ij bi = bj = B were combined to become the new number b (b + the number of times the combined addition of k), the combined number becomes f (i + j) can
be found this does meet Σai * k ^ bi = 1, n-1 and in all cases have been demonstrated induction
③n = 2
n = 1 and special, so special consideration should be n = 2
from n> 1 the conclusion that, b1 = b2 = B
because B ^ + K * A1 A2 B ^ = K 1 *
A1 + A2 = K ^ (- B)
Therefore, f (a1 + a2) = 1 , n = 1 may be changed, i.e., above He said absence a1> 1


Then it is obviously the dp, for each operation to consider adding an a, or for all of the k a by
the reduction of the time a legitimate sequence can be found where the absence of a decimal
ai is an integer and shall therefore dp when
used bitset optimization, the reduction of anti-DP, and then obtains a positive every operation
necessary to record the states restore DP (because of the bitset), each enumeration of operating state is present can be determined whether the original

code

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <bitset>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
using namespace std;

struct type{
    int a,b;
} b[17];
int p[17];
int a[17];
int ans[101];
bitset<2001> f[65536];
int n,K,L,i,j,k,l,sum,len,s,tot;

bool cmp(type a,type b)
{
    return a.b>b.b;
}

int main()
{
//  freopen("e.in","r",stdin);
    
    p[1]=1;
    fo(i,2,16)
    p[i]=p[i-1]<<1;
    
    scanf("%d%d",&n,&K);L=(p[n]<<1)-1;
    fo(i,1,n)
    scanf("%d",&a[i]),sum+=a[i];
    sum/=K;
    
    f[0][0]=1;
    fo(i,1,L)
    {
        fo(j,1,n)
        if (i&p[j])
        f[i]|=f[i^p[j]]<<a[j];
        
        fd(j,sum,1)
        if (f[i][j*K])
        f[i][j]=1;
    }
    
    if (!f[L][1])
    printf("NO\n");
    else
    {
        printf("YES\n");
        
        s=L;j=1;
        while (j)
        {
            if (j<=sum && f[s][j*K])
            {
                j*=K;
                ans[++len]=-1;
                continue;
            }
            
            fo(i,1,n)
            if (s&p[i] && j>=a[i] && f[s-p[i]][j-a[i]])
            {
                s-=p[i];
                j-=a[i];
                ans[++len]=i;
                
                break;
            }
        }
        
        j=0;
        fo(i,1,len)
        if (ans[i]==-1)
        ++j;
        else
        b[++tot]={a[ans[i]],-j};
        
        while (tot>1)
        {
            sort(b+1,b+tot+1,cmp);
            
            printf("%d %d\n",b[tot-1].a,b[tot].a);
            b[tot-1].a+=b[tot].a;
            
            --tot;
            while (!(b[tot].a%K))
            b[tot].a/=K,++b[tot].b;
        }
    }
}

Guess you like

Origin www.cnblogs.com/gmh77/p/11779812.html