【CF1139D】Steps to One(动态规划)

【CF1139D】Steps to One(动态规划)

题面

CF
你有一个数组,每次随机加入一个\([1,n]\)的数,当所有数\(gcd\)\(1\)时停止,求数组长度的期望。

题解

\(f[i]\)表示\(gcd\)\(i\)时的答案的期望。
考虑转移就是每次选一个数和\(i\)求个\(gcd\),那么计算一下变成每个可能的值的方案数直接暴力转移就行了。
复杂度似乎是两个\(log\)???

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
#define MOD 1000000007
#define MAX 100100
void add(int &x,int y){x+=y;if(x>=MOD)x-=MOD;}
int fpow(int a,int b){int s=1;while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}return s;}
int n,f[MAX],inv[MAX],mu[MAX];
vector<int> y[MAX];
int main()
{
    scanf("%d",&n);f[1]=0;mu[1]=1;inv[0]=inv[1]=1;
    for(int i=2;i<=n;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
    for(int i=1;i<=n;++i)for(int j=i;j<=n;j+=i)y[j].push_back(i);
    for(int i=1;i<=n;++i)for(int j=i+i;j<=n;j+=i)mu[j]-=mu[i];
    for(int i=1;i<=n;++i)
    {
        int p=n/i;
        if(i!=1)f[i]=1ll*(f[i]+p)*inv[n-p]%MOD;;
        add(f[0],f[i]+1);
        for(int j=i+i;j<=n;j+=i)
        {
            int d=j/i,s=0;
            for(int v:y[d])s+=mu[v]*(p/v);
            add(f[j],1ll*s*(f[i]+1)%MOD);
        }
    }
    f[0]=1ll*f[0]*inv[n]%MOD;
    printf("%d\n",f[0]);
    return 0;
}

转载于:https://www.cnblogs.com/cjyyb/p/10655396.html

假如我用bertopic对英文专利摘要文本进行了静态主题表示,在此基础上现在我需要用bertopic自带的topic_over_time动态主题建模结合调整c-TF-IDF 算法进行动态主题表示,动态主题表示设置时间戳 t1=2000-2010 年,t2=2011-2018 年,t3=2019-2024 年。最终,将当前阶段和前一阶段的 c-TF-IDF 平均值作为当前阶段的权重分数,取权重分数前 15 的单词作为动态主题的关键词,形成动态主题词列表。注意,已经进行切词、去除停用词、标点符号的英文专利摘要文本保存在’tokenized_abstract.csv’中,并且在静态主题建模时已经进行了加载,专利摘要对应的时间数据保存在’date.txt’中,尚未加载,已经执行的静态主题模型的参数设置如下:from sentence_transformers import SentenceTransformer Step 1 - Extract embeddings embedding_model = SentenceTransformer(“C:\Users\18267\.cache\huggingface\hub\models–sentence-transformers–all-mpnet-base-v2\snapshots\9a3225965996d404b775526de6dbfe85d3368642”) embeddings = np.load(‘clean_emb_last.npy’) print(f"嵌入的形状: {embeddings.shape}") Step 2 - Reduce dimensionality umap_model = UMAP(n_neighbors=7, n_components=10, min_dist=0.0, metric=‘cosine’,random_state=42) Step 3 - Cluster reduced embeddings hdbscan_model = HDBSCAN(min_samples=7, min_cluster_size=60,metric=‘euclidean’, cluster_selection_method=‘eom’, prediction_data=True) Step 4 - Tokenize topics Combine custom stop words with scikit-learn’s English stop words custom_stop_words = [‘h2’, ‘storing’, ‘storage’, ‘include’, ‘comprise’, ‘utility’, ‘model’, ‘disclosed’, ‘embodiment’, ‘invention’, ‘prior’, ‘art’, ‘according’, ‘present’, ‘method’, ‘system’, ‘device’, ‘may’, ‘also’, ‘use’, ‘used’, ‘provide’, ‘wherein’, ‘configured’, ‘predetermined’, ‘plurality’, ‘comprising’, ‘consists’, ‘following’, ‘characterized’, ‘claim’, ‘claims’, ‘said’, ‘first’, ‘second’, ‘third’, ‘fourth’, ‘fifth’, ‘one’, ‘two’, ‘three’,‘hydrogen’] Create combined stop words set all_stop_words = set(custom_stop_words).union(ENGLISH_STOP_WORDS) vectorizer_model = CountVectorizer(stop_words=list(all_stop_words)) Step 5 - Create topic representation ctfidf_model = ClassTfidfTransformer() All steps together topic_model = BERTopic( embedding_model=embedding_model, # Step 1 - Extract embeddings umap_model=umap_model, # Step 2 - Reduce dimensionality hdbscan_model=hdbscan_model, # Step 3 - Cluster reduced embeddings vectorizer_model=vectorizer_model, # Step 4 - Tokenize topics ctfidf_model=ctfidf_model, # Step 5 - Extract topic words top_n_words=50 ) 现在,请你给出实现这一操作的python代码帮我完成静态主题表示之后的动态主题表示。调整后的c-TF-IDF计算公式如下: c − T F − I D F w , c , r = ( f w , c , r f c + f w , c , r − 1 f c ) ⋅ log ⁡ ( 1 + M − c f w + 0.5 c f w + 0.5 ) 2 c−TF−IDF w,c,r ​ = 2 ( f c ​ f w,c,r ​ ​ ​ + f c ​ f w,c,r−1 ​ ​ ​ )⋅log(1+ cf w ​ +0.5 M−cf w ​ +0.5 ​ ) ​ 文字说明: “其中,( f_{w,c,r} ) 为第 ( r ) 阶段时,词 ( w ) 在聚类簇 ( c ) 中出现的频次,( f_c ) 表示聚类簇 ( c ) 中词数。( M ) 表示簇的平均单词数,( cf_w ) 表示词 ( w ) 在所有簇中出现频次。”
最新发布
03-15
<think>好的,我现在需要帮助用户完成动态主题建模。用户已经用BERTopic进行了静态主题建模,现在想用topic_over_time功能结合调整后的c-TF-IDF算法来做动态主题表示。时间分为三个阶段,最后要计算当前和前一阶段的平均值作为权重,取前15个词。 首先,我得确保用户的时间数据已经加载。用户提到时间数据在date.txt里,但还没加载。所以第一步应该是读取这个文件,处理成时间戳。可能需要检查日期的格式,比如是否是年份还是具体日期,是否需要转换为datetime对象。 接下来,用户已经进行了静态建模,所以可能已经有了topic_model对象。但动态建模需要时间信息,所以需要调用topic_model.topics_over_time方法。不过根据BERTopic的文档,可能需要使用文档的时间戳和已经生成的主题。这里需要注意参数的传递,比如文档的时间戳需要和之前的文档顺序一致。 然后是关于调整c-TF-IDF的计算公式。用户提供了新的公式,可能需要自定义ClassTfidfTransformer。原来的ctfidf_model是默认的,现在需要替换成自定义的。需要创建一个继承自ClassTfidfTransformer的子类,重写fit方法,按照新公式计算。 新公式中的变量需要理清:f_w,c,r是当前阶段r中词w在簇c的频次,f_c是簇c的总词数,M是簇的平均词数,cf_w是词w在所有簇中的总频次。计算时需要分阶段处理,可能需要访问每个时间段的统计信息。这里可能需要修改BERTopic内部的处理逻辑,或者利用现有的参数进行计算。 另外,用户提到最后要取当前阶段和前一阶段的平均值作为权重,取前15。这可能在提取关键词时处理,比如在得到各阶段的c-TF-IDF值后,对每个词计算两阶段的平均,再排序。但BERTopic的topics_over_time可能不支持直接这样处理,可能需要手动处理数据。 可能的步骤: 1. 加载时间数据,并文档对应。 2. 使用topic_model.topics_over_time生成动态主题,可能需要调整参数。 3. 自定义ctfidf_model,按照新公式计算。 4. 处理时间段划分,可能需要将时间数据分箱到t1, t2, t3。 5. 计算每个阶段的c-TF-IDF,然后计算当前和前一段的平均,取前15词。 需要注意,BERTopic的topics_over_time可能默认使用时间序列的划分方式,可能需要将时间戳分箱为用户指定的三个时间段。这可能需要先将日期转换为对应的阶段标签,如t1、t2、t3,然后传入给topics_over_time函数,或者使用时间窗口参数。 此外,自定义ctfidf_model需要理解原代码中的ClassTfidfTransformer的结构,确保新公式正确应用。可能需要参考原类的实现,调整其中的计算步骤。 最后,生成动态主题词列表时,需要根据权重分数筛选,可能需要从topic_model.get_topics()中提取各阶段的主题词,然后按照用户的规则计算权重,再排序取前15。 可能遇到的难点是如何将自定义的c-TF-IDF公式整合到BERTopic中,以及正确处理时间分箱和权重计算。需要查阅BERTopic的文档,看看是否支持自定义时间段的划分,或者是否需要手动处理时间数据,分阶段训练模型。</think>我将分步骤指导您实现动态主题建模,并提供完整代码及公式对应实现: ```python import pandas as pd import numpy as np from bertopic import BERTopic from bertopic.ctfidf import ClassTfidfTransformer from sklearn.feature_extraction.text import CountVectorizer # 自定义调整后的c-TF-IDF计算类 class AdjustedCTFIDF(ClassTfidfTransformer): def __init__(self): super().__init__() def fit(self, X: np.ndarray, multiplier: np.ndarray = None): """根据新公式调整计算""" X = X.T.toarray() # 转换为密集矩阵 n_samples, n_features = X.shape # 计算公式中的各项参数 M = X.sum(axis=1).mean() # 簇的平均单词数 cf = X.sum(axis=0) # 词在所有簇的出现频次 # 调整后的TF计算(当前阶段+前一阶段) adj_tf = (X[:, 1:] / X.sum(axis=1)[:, None] + X[:, :-1] / X.sum(axis=1)[:, None]) / 2 # 调整后的IDF计算 adj_idf = np.log(1 + ((M - cf + 0.5)/(cf + 0.5))) # 组合计算结果 c_tf_idf = adj_tf * adj_idf[None, :] self._ctfidf = c_tf_idf return self # 加载时间数据 with open('date.txt', 'r') as f: dates = [line.strip() for line in f.readlines()] # 转换为时间段标签 def time_period(year): year = int(year[:4]) # 假设日期格式为YYYY-MM-DD if 2000 <= year <= 2010: return "2000-2010" elif 2011 <= year <= 2018: return "2011-2018" else: return "2019-2024" # 创建时间段列表 time_labels = [time_period(date) for date in dates] # 加载预处理后的文本 docs = pd.read_csv('tokenized_abstract.csv')['text'].tolist() # 重新初始化模型(继承静态模型参数) topic_model = BERTopic( embedding_model=embedding_model, umap_model=umap_model, hdbscan_model=hdbscan_model, vectorizer_model=vectorizer_model, ctfidf_model=AdjustedCTFIDF(), # 使用自定义计算类 top_n_words=50 ) # 动态主题建模 topics_over_time = topic_model.topics_over_time( docs=docs, timestamps=time_labels, # 使用时间段标签 global_tuning=True, evolution_tuning=True ) # 生成动态主题词列表 def generate_dynamic_keywords(topic_model, n=15): dynamic_keywords = {} # 获取各时间段c-TF-IDF值 for period in ["2000-2010", "2011-2018", "2019-2024"]: # 获取当前阶段数据 current = topic_model.topics_over_time[ topic_model.topics_over_time.Timestamp == period] # 计算权重分数(当前阶段+前一阶段平均) if period == "2000-2010": weights = current.c_tf_idf.values else: prev_period = list(dynamic_keywords.keys())[-1] prev_weights = dynamic_keywords[prev_period]['weights'] weights = (current.c_tf_idf.values + prev_weights) / 2 # 获取前15关键词 sorted_idx = np.argsort(weights)[::-1][:n] keywords = [current.Words.iloc[0][i] for i in sorted_idx] dynamic_keywords[period] = { 'keywords': keywords, 'weights': weights } return dynamic_keywords # 执行生成 dynamic_keyword_list = generate_dynamic_keywords(topic_model) # 输出结果 for period, data in dynamic_keyword_list.items(): print(f"时间段 {period} 的关键词:") print(", ".join(data['keywords'])) print("\n") ``` 公式实现说明: 1. `AdjustedCTFIDF`类继承`ClassTfidfTransformer`并重写`fit`方法 2. 新计算公式分步实现: $$ c-TF-IDF_{w,c,r} = \frac{1}{2}\left(\frac{f_{w,c,r}}{f_c} + \frac{f_{w,c,r-1}}{f_c}\right) \cdot \log\left(1 + \frac{M - cf_w + 0.5}{cf_w + 0.5}\right) $$ 3. 其中: - $f_{w,c,r}$:通过`X[:, 1:]`获取当前阶段词频 - $f_{w,c,r-1}$:通过`X[:, :-1]`获取前一阶段词频 - $M$:通过`X.sum(axis=1).mean()`计算 - $cf_w$:通过`X.sum(axis=0)`计算 使用建议: 1. 确保日期格式`time_period`函数处理逻辑匹配 2. 最终结果存储在`dynamic_keyword_list`字典中 3. 可通过`topic_model.visualize_topics_over_time()`生成可视化图表 4. 权重分数阈值可根据实际效果调整 该代码实现了: 1. 时间数据的分段处理 2. 自定义c-TF-IDF计算 3. 跨时间段的权重平均 4. 动态关键词提取 5. 结果结构化输出
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值