July 26, 2019 (Mathematics, DP)

Suffering, exploding zero!!

Hey... Topics

prob1: A

Main idea of the title: Two operations: turning a bit over or different or a number in a set on the binary system of a number to find the minimum number of steps from(s) to(t\)

\ (sb) Question, Complete Water Question, Result (bfs) Queue Writing Wilted

The first operation can be converted to the second one, and each number can only be exclusive or once at most, just fool around with (bfs\). But the minimum step updates need to be made when entering the team, and whether updates are made as entry conditions, or they will blow up (don't ask me how I know)

Paste code:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;++i)
#define int long long
#define xx 270000
const int mod=998244353;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    for(;!isalnum(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
int que[xx][3];
int q[xx],all,ans[xx];
inline void bfs()
{
    int head=0,tail=-1;
    que[++tail][0]=0;
    que[tail][1]=0;
    que[tail][2]=0;
    while(head<=tail)
    {
        int w=que[head][0],u=que[head][1],v=que[head++][2];
        fur(i,w+1,all)
        {
            if(!ans[u^q[i]])
            {
                que[++tail][0]=i;
                que[tail][1]=u^q[i];
                ans[u^q[i]]=v+1;
                que[tail][2]=v+1;
            }
        }
    }
}
signed main()
{
    int t=in;
    q[1]=1;
    fur(i,2,18) q[i]=q[i-1]<<1;
    while(t--)
    {
        int n=in,m=in;all=18;
        fur(i,1,n) q[++all]=in;
        int res=0;
        memset(ans,0,sizeof(ans));
        bfs();
        ans[0]=0;
        fur(i,1,m)
        {
            int s=in,tt=in;
            res=(res+i*ans[s^tt]%mod)%mod;
        }
        printf("%lld\n",res);
    }
    return 0;
}

prob2: B

Topic: Given a string of strings (only 26 letters in English), find the shortest non-subsequence strings with the smallest dictionary order.

At first I thought it was a string problem, but later I thought it was a graph topic. How could I not imagine it was a greedy +hard (DP hard) problem (Xuejie hard ah). When the size of the string is less than 26, we can get the answer clearly. Through this nature, we can go back and forth (DP hard):___________

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;++i)
#define fdr(i,a,b) for(int i=a;i>=b;--i)
#define xx 500010
#define inf 0x7fffffff
int f[xx][27],g[xx],pos[xx],n;
char ch[xx];
inline void dfs(int q,int len)
{
    if(len==1)
    {
        fur(i,1,26)
        {
            if(f[q][i]==n+1)
            {
                printf("%c",i+'a'-1);
                return;
            }
        }
    }
    fur(i,1,26)
    {
        if(g[f[q][i]]==len)
        {
            printf("%c",i+'a'-1);
            dfs(f[q][i]+1,len-1);
            break;
        }
    }
}
int main()
{
    scanf("%s",ch+1);
    n=strlen(ch+1);
    fur(i,1,26) f[n+1][i]=n+1,pos[i]=n+1;
    g[n+1]=1;
    fdr(i,n,1)
    {
        fur(j,1,26) f[i][j]=f[i+1][j];
        f[i][ch[i]-'a'+1]=i;
        g[i]=inf;
        fur(j,1,26) g[i]=min(g[i],g[pos[j]]+1);
        pos[ch[i]-'a'+1]=i;
    }
    int ans=inf;
    fur(i,1,26)
    {
        if(f[1][i]==n+1)
        {
            printf("%c\n",i+'a'-1);
            return 0;
        }
        ans=min(ans,g[f[1][i]]);
    }
    dfs(1,ans);
    printf("\n");
    return 0;
}

prb3: C

Main idea of the title: Given the (n*m) matrix, find the number of three-point-to-three-point collinear schemes

I don't want to say anything because I made a mistake in the exam.

#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;++i)
#define int long long
const int xx=1e7+10;
const int n6=166666668;
const int mod=1e9+7;
int phi[xx],prime[xx],cnt=0,ans=0,m,n;
bool mark[xx];
inline void handle()
{
    phi[1]=1;
    fur(i,2,n)
    {
        if(!mark[i]) phi[i]=i-1,prime[++cnt]=i;
        for(int j=1;j<=cnt&&prime[j]*i<=n;++j)
        {
            mark[i*prime[j]]=true;
            if(i%prime[j]) phi[i*prime[j]]=phi[i]*(prime[j]-1);
            else
            {
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
        }
    }
}
inline int calc(int x,int d,int u){return (x-u*d+x-d)*u/2%mod;}
inline int C(int nm){return nm*(nm-1)%mod*(nm-2)%mod*n6%mod;}
signed main()
{
    scanf("%lld%lld",&n,&m);
    if(n>m) swap(n,m);
    --n;--m;
    handle();
    fur(i,1,n)
    {
        int tmp=phi[i];
        tmp=(tmp*calc(n+1,i,n/i))%mod;
        tmp=(tmp*calc(m+1,i,m/i))%mod;
        ans=(ans+tmp)%mod;
    }
    ans=(ans-((n+1)*n/2%mod)*((m+1)*m/2%mod)%mod+mod)%mod;
    ans=(ans<<1)%mod;
    ans=(ans+(n+1)*C(m+1)%mod+(m+1)*C(n+1)%mod)%mod;
    printf("%lld\n",ans);
    return 0;
}

prob4: D

Main idea: Given an arbitrary graph composed of (n) labeled nodes, find the sum of the (k) power of the number of trees in the graph.

Knowledge Reserve: The Second Kind of Stirling Number+prufer Sequence

And the class mood is not good, and did not listen carefully, leading to this problem will not, the scale is not understood, directly \\\\\\\\\\

(This crushing is disgusting):

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#define LL long long
#define N 50005
using namespace std;

const int mo=998244353,G=3;
int n,K,rev[N*3],len,num,g[25][N];
LL S[25][25],jc[N],ny[N],wn[50],f[N*3],h[N*3],ans;

LL qp(LL x,LL y) {
    LL res=1;
    for(;y;y>>=1ll,x=x*x%mo)
        if(y&1ll) res=res*x%mo;
    return res;
}
void pre() {
    jc[0]=ny[0]=1;
    for(int i=1;i<=n;++i) jc[i]=jc[i-1]*i%mo;
    ny[n]=qp(jc[n],mo-2);
    for(int i=n-1;i>=0;--i) ny[i]=ny[i+1]*(i+1)%mo;
    f[1]=1*ny[0];
    for(int i=2;i<=n;++i) f[i]=qp(i,i-2)*ny[i-1]%mo;
    S[0][0]=1;
    for(int i=1;i<=K;++i)
        for(int j=1;j<=i;++j)
            S[i][j]=(S[i-1][j]*j%mo+S[i-1][j-1])%mo;
    for(len=1,num=0;len<=n+n;len<<=1,num++);
    for(int i=1;i<len;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(num-1));
    for(int i=0;i<=45;++i) wn[i]=qp(G,(mo-1)/(1<<i));
}
void ntt(LL *x,int sign) {
    for(int i=0;i<len;++i) if(i<rev[i]) swap(x[i],x[rev[i]]);
    for(int k=2,e=1;k<=len;k<<=1,e++) {
        for(int i=0;i<len;i+=k) {
            LL *a=x+i,*b=x+i+(k>>1); LL u,v,w=1;
            for(int j=0;j<(k>>1);++j,w=w*wn[e]%mo) {
                u=a[j],v=b[j]*w%mo;
                a[j]=u+v; a[j]>=mo?a[j]-=mo:0;
                b[j]=u-v; b[j]<0?b[j]+=mo:0;
            }
        }
    }
    if(sign==-1) {
        int inv=qp(len,mo-2);
        for(int i=0;i<len;++i) x[i]=x[i]*inv%mo;
        reverse(x+1,x+len);
    }
}
LL C(LL x,LL y) {return x>=y?jc[x]*ny[y]%mo*ny[x-y]%mo:0;}
int main()
{
    scanf("%d%d",&n,&K);
    pre();
    g[0][0]=1; ntt(f,1);
    for(int i=1;i<=K;++i) {
        memset(h,0,sizeof(h[0])*len);
        for(int j=0;j<=n;++j) h[j]=1ll*g[i-1][j]*ny[j]%mo;
        ntt(h,1);
        for(int j=0;j<len;++j) h[j]=h[j]*f[j]%mo;
        ntt(h,-1);
        for(int j=1;j<=n;++j) g[i][j]=h[j]*jc[j-1]%mo;
    }
    for(int i=1;i<=n;++i) {
        LL tmp=qp(2,1ll*(n-i)*(n-i-1)/2ll)*C(n,i)%mo;
        for(int j=1;j<=K;++j) {
            ans+=g[j][i]*S[K][j]%mo*jc[j]%mo*tmp%mo;     //!!!!!
            ans>=mo?ans-=mo:0;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

Keywords: PHP less

Added by SsirhC on Wed, 07 Aug 2019 04:02:49 +0300