[矩阵快速幂] Atcoder AGC003 F. Fraction of Fractal

本文介绍了一种使用矩阵快速幂方法解决特定连通块转移问题的方法。通过判断初始状态的特性,利用矩阵运算高效计算经过多次转移后的连通块数量,适用于竞赛编程中的复杂问题。

很神的题!!!

首先观察一下每次转移

如果初始的图案存在某一行 i,满足行的两个端点为黑,且存在某一列也是满足这样的条件,那么答案就是1,因为原来就连通的黑块转移后的图案也是联通的。

如果行和列都不满足,因为每次转移答案都会乘 x, 那么答案就是 xk1 ,其中 x 为初始图案中的黑块数量。

如果只有行满足这样的条件(列满足的话转一下图案),

x 等于黑块的数量, y 等于初始图像中 ai,jai,j+1 都为黑的 (i,j) 数量, z 为几行满足上面的条件

那么每次转移就有

  • x=x2
    • y=xy+yz
    • z=z2

    这个东西退一下可以知道…

    用矩阵转移就好了…

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <assert.h>
    
    using namespace std;
    
    typedef long long ll;
    
    const int N=1010,P=1e9+7;
    
    struct mat{
      int a[2][2];
      mat(){ a[0][0]=a[1][1]=a[0][1]=a[1][0]=0; }
      int *operator [](int x){
        return a[x];
      }
      friend mat operator *(mat a,mat b){
        mat c;
        c[0][0]=(1LL*a[0][0]*b[0][0]+1LL*a[0][1]*b[1][0])%P;
        c[0][1]=(1LL*a[0][0]*b[0][1]+1LL*a[0][1]*b[1][1])%P;
        c[1][0]=(1LL*a[1][0]*b[0][0]+1LL*a[1][1]*b[1][0])%P;
        c[1][1]=(1LL*a[1][0]*b[0][1]+1LL*a[1][1]*b[1][1])%P;
        return c;
      }
    };
    
    mat u;
    int n,m;
    char a[N][N],b[N][N];
    ll k;
    
    inline int judge(){
      for(int i=1;i<=n;i++)
        if(a[i][1]=='#' && a[i][m]=='#') return 1;
      return 0;
    }
    
    inline void turn(){
      for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
          b[m-j+1][i]=a[i][j];
      swap(n,m); memcpy(a,b,sizeof(a));
    }
    
    inline int Pow(int x,ll y){
      int ret=1;
      for(;y;y>>=1,x=1LL*x*x%P) if(y&1) ret=1LL*ret*x%P;
      return ret;
    }
    
    inline mat Pow(mat x,ll y){
      mat ret=u;
      for(;y;y>>=1,x=x*x) if(y&1) ret=ret*x;
      return ret;
    }
    
    int main(){
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      u[0][0]=u[1][1]=1;
      scanf("%d%d%lld",&n,&m,&k);
      int cnt=0;
      for(int i=1;i<=n;i++){
        scanf("%s",a[i]+1);
        for(int j=1;j<=m;j++)
          cnt+=a[i][j]=='#';
      }
      int A=judge(),B=(turn(),judge()); turn();
      if((A && B) || !k) return puts("1"),0;
      if(!A && !B) return printf("%d\n",Pow(cnt,k-1)),0;
      if(!A) turn();
      int c=0,b=0; for(int i=1;i<=n;i++) c+=(a[i][1]=='#' && a[i][m]=='#');
      for(int i=1;i<=n;i++)
        for(int j=1;j<m;j++)
          b+=(a[i][j]=='#' && a[i][j+1]=='#');
      mat w,ans; w[0][0]=cnt; w[0][1]=b; w[1][1]=c;
      ans=Pow(w,k-1);
      printf("%d\n",(ans[0][0]+P-ans[0][1])%P);
      return 0;
    }
    
<think>首先,用户的问题是:“我想查找Flink任务中taskmanager.memory.network.fraction和taskmanager.memory.managed.size的配置方法”。所以,我需要提供关于这两个配置参数的配置方法。 从系统指令中,我必须使用中文回答,并确保回答结构清晰,帮助用户逐步解决问题。同时,我需要引用提供的引用内容,并在末尾添加引用标识。 参考的引用内容: - 引用[1]: 提到配置Total Memory,但没有直接涉及这两个参数。 - 引用[2]: 建议优先修改网络缓存占比taskmanager.memory.network.fraction和托管内存占比taskmanager.memory.managed.fraction,间接影响任务内存。手动指定固定内存量参数容易导致冲突。 - 引用[3]: 列出配置方式,包括taskmanager.memory.flink.size、taskmanager.memory.process.size、taskmanager.memory.task.heap.size和taskmanager.memory.managed.size。 - 引用[4]: 详细说明如何修改托管内存和网络内存。托管内存可以通过taskmanager.memory.managed.size指定大小或taskmanager.memory.managed.fraction指定占比。网络内存通过taskmanager.memory.network.fraction指定占比。还提到托管内存的应用场景,如RocksDB状态后端,使用HashMap状态后端时可设置为0。 - 引用[5]: 讨论内存管理机制,包括如何调整各区域大小。 用户特别关注taskmanager.memory.network.fraction和taskmanager.memory.managed.size的配置方法。 关键点: - **taskmanager.memory.managed.size**: 用于明确指定托管内存的大小。引用[4]说:“通过 taskmanager.memory.managed.size 明确指定其大小。” 如果未指定,则使用fraction计算。 - **taskmanager.memory.network.fraction**: 用于指定网络内存占总内存的占比。引用[4]说:“修改网络内存(Network Memory)方式: taskmanager.memory.network.fraction 指定在Flink 总内存中的占比。” 没有提到size版本,因为网络内存通常通过fraction配置。 在Flink文档中,taskmanager.memory.network.fraction是配置网络内存的占比,而taskmanager.memory.network.min和.max可以指定最小和最大值,但用户没有提到这些。用户只问了.fraction.managed.size。 配置方法: 1. **taskmanager.memory.managed.size**: 直接指定一个固定大小,例如"1g" for 1GB。引用[4]说:“通过 taskmanager.memory.managed.size 明确指定其大小。” 如果同时指定size和fraction,size优先。 2. **taskmanager.memory.network.fraction**: 指定一个比例,例如0.1 for 10%。引用[4]说:“taskmanager.memory.network.fraction 指定在Flink 总内存中的占比。” 最佳实践: - 引用[2]建议优先使用fraction来间接调整,以避免手动指定固定内存导致冲突。 - 引用[4]提到,在特定场景下,如使用HashMap状态后端时,可以将托管内存设置为0。 回答结构: 1. **介绍参数**: 简要解释每个参数的作用。 2. **配置方法**: 提供具体的配置步骤和示例。 3. **注意事项**: 包括最佳实践和潜在问题。 4. **生成相关问题**: 在末尾添加相关问题。 使用中文回答。 确保引用来源:在相关段落末尾添加引用标识,如[^2]。 现在,组织回答: - 开头:直接回应用户问题。 - 主体: - 解释taskmanager.memory.managed.size的配置方法。 - 解释taskmanager.memory.network.fraction的配置方法。 - 结合引用给出建议。 - 结尾:生成相关问题。 相关引用: - For taskmanager.memory.managed.size: 引用[4]直接提到。 - For taskmanager.memory.network.fraction: 引用[2]和[4]提到。 - 引用[5]提供一般背景。 最终回答:</think>### Flink任务中taskmanager.memory.network.fraction和taskmanager.memory.managed.size的配置方法 在Apache Flink中,TaskManager的内存配置对任务性能至关重要。`taskmanager.memory.network.fraction` 和 `taskmanager.memory.managed.size` 是两个关键参数,分别用于控制网络内存和托管内存的分配。下面我将逐步解释它们的配置方法,包括具体步骤、示例和注意事项,确保配置安全可靠。 #### 1. **参数解释与配置方法** - **`taskmanager.memory.managed.size`(托管内存大小)**: - **作用**:托管内存主要用于状态后端存储(如RocksDB状态后端),直接指定其固定大小(例如GB或MB单位)。如果未指定,Flink会基于总内存占比计算。 - **配置方法**: - 直接在Flink配置文件(如 `flink-conf.yaml`)中设置一个固定值,格式为大小字符串(如"1g"表示1GB)。 - **示例**:`taskmanager.memory.managed.size: "512m"` 表示分配512MB托管内存。 - 如果同时指定了`taskmanager.memory.managed.fraction`(占比参数),则`managed.size`优先级更高,Flink会忽略fraction计算[^4]。 - **适用场景**:当使用RocksDB状态后端时,托管内存应足够大以存储状态数据;但如果使用HashMap状态后端,可设置为"0"以释放内存给其他组件[^4]。 - **`taskmanager.memory.network.fraction`(网络内存占比)**: - **作用**:网络内存用于数据传输缓存(如Shuffle操作),通过指定占总内存的比例来间接控制大小(无法直接设置固定大小)。 - **配置方法**: - 在配置文件中设置一个比例值(0.0到1.0之间),Flink会根据总内存自动计算网络内存的实际大小。 - **示例**:`taskmanager.memory.network.fraction: 0.1` 表示网络内存占总内存的10%。 - 默认值为0.1,但可根据网络流量调整:高流量场景可适当增加(如0.15),低流量可减少(如0.05)以节省资源[^2][^4]。 - **注意**:网络内存没有直接的"size"参数,仅通过fraction配置;Flink内部会确保其不低于最小阈值(可通过`taskmanager.memory.network.min`覆盖)。 #### 2. **配置步骤与示例** - **步骤**: 1. 打开Flink的配置文件 `flink-conf.yaml`。 2. 添加或修改以下参数(根据实际需求调整值)。 3. 保存文件并重启Flink集群使配置生效。 - **完整配置示例**: ```yaml # 设置托管内存固定大小为512MB taskmanager.memory.managed.size: "512m" # 设置网络内存占比为总内存的8% taskmanager.memory.network.fraction: 0.08 ``` - 在此示例中,托管内存被明确指定为512MB,网络内存占比降低到0.08(默认0.1),适用于网络流量较小的场景。 #### 3. **注意事项与最佳实践** - **避免手动冲突**:优先使用比例参数(如`network.fraction`和`managed.fraction`)进行间接调整,而非直接指定固定大小。手动设置过多固定值(如`managed.size`)可能导致内存配额冲突,引发部署失败[^2]。 - **性能调优建议**: - 在RocksDB状态后端下,增加托管内存(例如通过`managed.size`)能提升状态访问速度;但使用HashMap后端时,建议设置`taskmanager.memory.managed.size: "0"`以最大化任务堆内存[^4]。 - 网络内存占比(`network.fraction`)应根据集群网络流量动态调整:高并发任务可提高到0.15,低流量任务可降至0.05以释放资源[^4]。 - **总内存协调**:这些参数依赖总内存(如`taskmanager.memory.flink.size`)。建议先配置总内存,再调整比例参数,以确保各组件平衡[^1][^5]。 - **监控与验证**:配置后,通过Flink Web UI或日志检查实际内存使用,确保无溢出或浪费。 #### 4. **常见问题解答** - **Q: 如果同时设置`managed.size`和`managed.fraction`,哪个生效?** A: `taskmanager.memory.managed.size`优先级更高,Flink会忽略fraction参数[^4]。 - **Q: 网络内存能否直接设置固定大小?** A: 不能,只能通过`network.fraction`间接控制;但可通过`taskmanager.memory.network.min`和`.max`设置最小/最大值作为补充。 - **Q: 配置错误如何处理?** A: 如果部署失败,检查日志中的内存冲突提示;通常需减少固定大小参数,改用比例参数简化配置[^2]。 通过以上方法,您可以安全地优化TaskManager内存,提升Flink任务稳定性和性能。如果需要更深入调优,建议参考[Flink官方文档](https://nightlies.apache.org/flink/flink-docs-stable/docs/deployment/memory/mem_setup/)。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值