其他分享
首页 > 其他分享> > 03-14考试总结

03-14考试总结

作者:互联网

Test0314

嘲讽垃圾选手的毒瘤出题人

你怎么不去吃\(**\)呢


T1

得分情况

预计分数 : 30pts
实际得分 : 80pts

考虑DP , 得到\(O(n^3)\)做法
优化 , 得到\(O(n*(k-n)^2)\)做法
得到毒瘤出题人的馈赠 , 获得额外50pts

正解

多项式优化DP , 我不会 所以不改了


T2

得分情况

预计分数 : 10pts
实际得分 : 10pts

\(O(n)\)模拟 这能写挂?
当然不可能过1e18的

正解

你考虑这个\(f\)的意义 , 可以发现 看题解 是这个 :

将 \(n\) 拆分为 : \(\sum_{i=0}^{...} a[i]*k^i\)的方案数
其中 , \(a[i]\) 取任意非负数

考虑DP , 设 :
\(f[i][j]\)为 : 用不超过\(k^j\)的任意个数凑出\(k^i\)的方案数
\(g_1[j][t]\)为 : 用不超过\(k^t\)的任意个数凑出\(j*k^{i-1}\)的方案数
于是我们有 :
\(f[i][i]=1\) , \(g_1[k][t]=f[i][t]\)
其中 , \(g_1\)为临时数组 , 对于每个\(i\)都要使用一次 , 具体转移见代码

\(h[i][j]\)为 : 用不超过\(k^j\)的任意个数凑出\(n\)的\(k^0...k^{i}\)项的方案数
\(g_2[j][t]\)为 : 用不超过\(k^t\)的任意个已经凑出\(n\)的\(k^0...k^{i-1}\)项
现在在凑\(k^i\)项 , 当前凑到了\(j*k^i\)的方案数 , 具体转移见代码

然后用上面的这些就可以计算用不超过\(k^j\)的任意个数凑出\(n\)的方案数了 , 也就是答案

上代码

#include<bits/stdc++.h>
#define r(a) a=read<int>()
#define rl(a) a=read<ll>()
#define MAXN(a) ((max##a)+10)
using namespace std;

typedef long long ll;

const int mod=1e9+7;
const int maxk=10,maxm=120;

namespace Math{
    inline void Add(int &u,int v){
        u=(u%mod+v%mod)%mod;return;
    }
}

using Math::Add;

int K;
__int128 n;

int f[MAXN(m)][MAXN(m)];
int g[MAXN(m)][MAXN(m)];
int h[MAXN(m)][MAXN(m)];

template<class T>inline T read();

inline int calc(){
    int m=(int)(log((long double)n)/log(K)),res=0;
    memset(f,0,sizeof(f));memset(g,0,sizeof(g));memset(h,0,sizeof(h));
    f[0][0]=h[0][0]=1;
    for(int i=1;i<=m;i=-~i){
        for(int j=1;j<=K;j=-~j)
            for(int t=0;t<=i;t=-~t)
                g[j][t]=(j==1)?(f[i-1][t]):(0); 
                        //清空g并赋初值
        for(int j=2;j<=K;j=-~j)
            for(int t=0;t< i;t=-~t)
                for(int k=0;k<=t;k=-~k)
                    g[j][t]=(g[j][t]+1ll*g[j-1][k]*f[i-1-k][t-k]%mod)%mod;
                        // lim=t时 凑出 j*K^(i-1)
                        // 那么设前面凑出了(j-1)*K^(i-1) , lim=k
                        // 加入的元素lim [k,t]
                        // 有公因数 K^k , 提出 , lim [0,t-k] , 转移方案数变为 f[i-1-k][t-k] (都除了K^k)
        for(int t=0;t<=i;t=-~t)
            f[i][t]=g[K][t]+(i==t);
    }
    for(int i=0;i<=m;i=-~i){
        int lim=n%K;n/=K;
        for(int j=0;j<=lim;j=-~j)
            for(int t=0;t<=i;t=-~t)
                g[j][t]=(j)?(0):(h[i][t]);  
                        //同上
        for(int j=1;j<=lim;j=-~j)
            for(int t=0;t<=i;t=-~t)
                for(int k=0;k<=t;k=-~k)
                    g[j][t]=(g[j][t]+1ll*g[j-1][k]*f[i-k][t-k]%mod)%mod;
                        // 此处g与上相似  
                        // lim = t 时 凑出了前i-1位 并且第i位凑到了j
                        // 其他同上
        for(int t=0;t<=i;t=-~t){
            h[i+1][t]=g[lim][t];
            if(i==m)Add(res,h[m+1][t]);
        }
    }
    return res;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("j.in","r",stdin);
    freopen("j.out","w",stdout);
#endif
    int r(T);
    while(T--){
        r(K),n=read<__int128>();
        printf("%d\n",calc());
    }return 0;
}

template<class T>inline T read(){
    T sum=0,f=1;char k=getchar();
    for(;k< '0'||'9'< k;k=getchar())
        if(k=='-')f=-1;
    for(;'0'<=k&&k<='9';k=getchar())
        sum=(sum * 10)+(k^48);
    return sum*f;
}


T3

得分情况

预计分数 : 0pts
实际得分 : 0pts

样例没过你想啥呢?
实际上想到了正解
然而Sap打错 + 二分图建错
只能以"想对了"安慰一下自己了quq

正解

考虑偶数时刻在\((x,y)\) , 一步以内的都跑了 , 走一步啥都莫得
你发现你只能在走两步去打野 , 所以相邻的是吃不到的
然后考虑为啥不相邻的能吃 , 发现你可以停在原地 , 这样你就改变了在\((x,y)\)的时间的奇偶性
完事 , 对网格图染色 , 跑最大独立集
上代码

#include<bits/stdc++.h>
#define r(a) a=read<int>()
#define rl(a) a=read<ll>()
using namespace std;

typedef long long ll;
const ll inf=1ll<<62;

struct Maxflow{
    struct edge{
        int v,next;ll flow;
    }e[100010];
    int n,tail,S,T;
    int head[10010];
    int d[10010],gap[10010];
    inline void init(){
        for(int i=1;i<=n;i=-~i)
            head[i]=d[i]=gap[i]=0;
        n=0,tail=1;
    }
    inline void add(int u,int v,ll flow){
        e[++tail].next=head[u],head[u]=tail;
        e[tail].v=v,e[tail].flow=flow;
        e[++tail].next=head[v],head[v]=tail;
        e[tail].v=u,e[tail].flow=0;
    }
    Maxflow(){init();}
    ll dfs(int u,ll flow){
        if(u==T)return flow;
        ll res=flow;
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].v;
            if(e[i].flow>0&&d[u]==d[v]+1){
                ll det=dfs(v,min(res,e[i].flow));
                e[i].flow-=det,e[i^1].flow+=det;res-=det;
                if(res==0)return flow;
            }
        }
        if((--gap[d[u]])==0)d[S]=n;
        gap[++d[u]]++;
        return flow-res;
    }
    inline ll slove(){
        ll res=0;gap[0]=n;
        while(d[S]<n){res+=dfs(S,inf);}
        return res;
    }
}G;

int n,m;
ll Val[101][101];

template<class T>inline T read();

inline int id(int x,int y){return (x-1)*m+y;}

int main(){
#ifndef ONLINE_JUDGE
    freopen("zjb.in","r",stdin);
    freopen("zjb.out","w",stdout);
#endif
    int r(T);
    while(T--){
        r(n),r(m);
        for(int i=1;i<=n;i=-~i)
            for(int j=1;j<=m;j=-~j)
                rl(Val[i][j]);
        ll res=0;
        for(int i=1;i<=n;i=-~i)
            for(int j=1;j<=m;j=-~j)
                res+=Val[i][j];
        G.init();
        G.S=n*m+1,G.T=G.S+1;G.n=G.T+1;
        for(int i=1;i<=n;i=-~i){
            for(int j=1;j<=m;j=-~j){
                int d=(i+j)&1;
                if(d){
                    G.add(G.S,id(i,j),Val[i][j]);
                    if(i>1)G.add(id(i,j),id(i-1,j),1e18);
                    if(i<n)G.add(id(i,j),id(i+1,j),1e18);
                    if(j>1)G.add(id(i,j),id(i,j-1),1e18);
                    if(j<m)G.add(id(i,j),id(i,j+1),1e18);
                }
                else G.add(id(i,j),G.T,Val[i][j]);
            }
        }
        //printf("%lld\n",res);
        res-=G.slove();
        printf("%lld\n",res);
    }
    return 0;
}

template<class T>inline T read(){
    T sum=0,f=1;char k=getchar();
    for(;k< '0'||'9'< k;k=getchar())
        if(k=='-')f=-1;
    for(;'0'<=k&&k<='9';k=getchar())
        sum=(sum<<1)+(sum<<3)+(k^48);
    return sum*f;
}

标签:03,14,int,res,ll,凑出,read,MAXN,考试
来源: https://www.cnblogs.com/Pump-six/p/10532980.html