gym102007 E

本文探讨了离散数学在算法竞赛中的应用,通过预处理排列总数,采用动态规划和容斥原理解决复杂问题,避免重复计算,最终计算出合法与非法方案数。

我计划预习五个小时离散,然后hmc补了这道他自认为非常的裸并且很傻逼自己可以一眼秒的简单题,然后给我讲了讲,然后我失去了一整晚的生命迹象。

首先我们可以发现一个神奇的现象,啊,先排个序,然后我们会发现,一个数 是 合法的(指左边的全部小于等于它,右边的全部大于等于它),当且仅当它在自己拍完序的位置上。

先不考虑很多相同的。 所以我们可以怎么做呢。从左到右枚举每个 合法的数,然后从左到右 枚举 起点。这样考虑,用dp[n]表示 从 1到 n ,n是合法的数的时候的方案数,ans[n]表示从1到n , 不合法的方案数。 c[n] 表示从 1 到 n 的 排列总数。 显然 。。。好难描述。    

唔,显然我们这样枚举会有很多重复的情况对吧。  艹,我先把hmc讲给我我听懂了的复述一下,一个数是 合法的 方案数, 就是 它左边的数xjb排和右边的数xjb排然后乘起来吧。

好啊其实我觉得他就说了这一局有用的。

所以我们可以采用 总排列数-所有合法情况。然后合法情况会有重复的,这个时候就要进行类似容斥的操作对不对。ex: 1,2  1,2;被计算了两次

所以我们可以 计算出 左边 不合法的 方案数。 用不合法的 再去乘 右边合法的 就一定不会和 之前的重复了,因为之前计算的是左边的合法的。

那么首先我们要知道每个子区间的排列总数,可以边计算顺便枚举,也可以先预处理出来。我比较傻逼混在一起就神志不清了就预处理出来的。

然后我们用 ans[i] 表示 到i 为止 的答案, dp[i]表示到 i为止 合法的 方案数。

第一层枚举 现在的区间 ,[1,i]; 第二层枚举 子区间, j  from 1 to i  ;

然后维护就好了。

emmm你要是不知道费马小定理的话,,,我也木有办法  也可以用递推式求对不对。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll mod = 1e9+9;
 5 const int N = 5005;
 6 ll inv[N];
 7 ll n,c[N][N],a[N];
 8 ll qpow(ll a,ll x){
 9     ll res = 1;
10     while (x){
11         if(x&1)
12             res=res*a%mod;
13         a=a*a%mod;
14         x>>=1;
15     }
16     return res;
17 }
18 void init(){
19     inv[1]=1;
20     for(int i=2;i<=5000;i++)
21         inv[i]=qpow(i,mod-2);
22 }
23 void slove(int n){
24     map<int,int> mp;
25     for(int i=1;i<=n;i++){
26         c[i][i-1]=1;
27         mp.clear();
28         for(int j=i;j<=n;j++){
29             c[i][j]=c[i][j-1]*(j-i+1)%mod*inv[++mp[a[j]]]%mod;
30         }
31         c[i+1][i]=1;
32     }
33 }
34 ll dp[N],ans[N];
35 int main(){
36     init();
37     ios::sync_with_stdio(false);
38     cin>>n;
39     for(int i=1;i<=n;i++){
40         cin>>a[i];
41     }
42     sort(a+1,a+1+n);
43     slove(n);
44     ans[0]=1;
45     for(int i=1;i<=n;i++){
46         for(int j=1;j<=i;j++){
47             dp[i]=(dp[i]+ans[j-1]*c[j+1][i])%mod;
48         }
49         //cout<<dp[i]<<' ';
50         ans[i]=(c[1][i]-dp[i]+mod)%mod;
51         //cout<<ans[i]<<endl;
52     }
53     cout<<ans[n]<<endl;
54 }
View Code

 

转载于:https://www.cnblogs.com/MXang/p/10182791.html

### 创建自定义环境的流程 在 OpenAI Gym 中创建自定义环境是一个相对简单的过程,主要分为以下几个方面: #### 1. 自定义环境的基础结构 为了创建一个新的环境,需要继承 `gym.Env` 类并实现其核心方法。以下是必要的组件及其作用[^1]: - **初始化函数 (`__init__`):** 设置初始状态和其他参数。 - **重置函数 (`reset`):** 返回环境的初始观察值,在每次训练开始前调用。 - **步进函数 (`step`):** 接收动作作为输入,返回下一步的状态、奖励以及是否结束标志。 - **渲染函数 (`render`):** 可选,用于可视化当前环境。 #### 2. 编写自定义环境代码 下面展示了一个简单的例子来说明如何编写一个基本的自定义环境[^3]: ```python import gym from gym import spaces class CustomEnv(gym.Env): """Custom Environment that follows gym interface""" metadata = {'render.modes': ['console']} def __init__(self, param=0.5): super(CustomEnv, self).__init__() # Define action and observation space self.action_space = spaces.Discrete(2) # Example: Two possible actions (e.g., move left or right) self.observation_space = spaces.Box(low=-1, high=1, shape=(1,), dtype=float) self.state = None self.param = param def reset(self): """ Reset the state of the environment to an initial state. Returns: Initial observation. """ self.state = [0] return self.state def step(self, action): """ Execute one time step within the environment. Args: action: Action taken by agent. Returns: Observation, reward, done flag, info dictionary. """ self.state += [action * self.param] reward = -abs(sum(self.state)) # Simplified example for demonstration purposes done = abs(sum(self.state)) >= 1 # End condition based on accumulated value exceeding threshold return self.state.copy(), reward, done, {} def render(self, mode='console'): if mode != 'console': raise NotImplementedError() print(f'State: {self.state}') ``` 此代码片段展示了如何通过继承 `gym.Env` 来构建新的环境类,并实现了必需的方法。 #### 3. 注册自定义环境至 Gym 为了让其他模块能够识别新创建的环境,需将其注册到 Gym 的环境中去。可以通过如下方式完成这一操作: ```python from gym.envs.registration import register register( id='CustomEnv-v0', entry_point='custom_env_module:CustomEnv', # Replace with actual module path where your class resides max_episode_steps=300, ) ``` 这里假设 `CustomEnv` 被放置在一个名为 `custom_env_module.py` 文件中的顶层命名空间下。如果路径不同,则应调整 `entry_point` 参数以匹配实际位置。 #### 总结 综上所述,要开发一个适用于强化学习研究或者应用项目的个性化模拟器,可以遵循上述指导原则来进行设计与编码工作。这不仅限于理论上的探讨,还涉及到了具体实践层面的操作指南[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值