51Nod1190 最小公倍数之和 V2

本文介绍了一种使用繁衍反演的方法来解决特定数学问题:求解Σlcm(i,b)(a≤i≤b)的计算过程。通过巧妙的数学变换和差分操作,并结合高效的代码实现,最终得出了解决方案。

题目看这里

繁衍反演真好玩

来看看这个题的式子

求Σlcm(i,b) (a<=i<=b)

首先不难发现以下这样的变换


让后做一下差分就得到答案,注意这题比较卡时间,需要比较好的优化

#pragma GCC opitmize("O3")
#pragma G++ opitmize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 40010
#define LL long long
#define M 1000000007
using namespace std;
bool vis[N];
int t,w[N],n;
inline LL F(LL i,int m){ return (i+i*m)*m>>1; }
inline void rd(int& x){
    char c=getchar(); x=0;
    for(;c>='0' && c<='9';c=getchar()) x=(x<<3)+(x<<1)+(c^48);
}
inline void out(int x){
    char c[10]; int j=0;
    for(;x;x/=10) c[++j]=x%10;
    for(;j;--j) putchar(c[j]^48); putchar('\n');
}
int init(){
    n=40000;
    for(int i=2;i<=n;++i){
        if(!vis[i]) w[++t]=i;
        for(int j=1,k;j<=t&&(k=i*w[j])<=n;++j){
            vis[k]=1;
            if(i%w[j]==0) break; 
        }
    }
}
int p[210],k[210],cnt;
struct D{ int d,mu; } d[10000];
inline bool c1(D x,D y){ return x.d<y.d; }
inline void dfs(int i,int S,int m){
    if(i>t){ d[++cnt]=(D){S,m}; return; }
    dfs(i+1,S,m);
    dfs(i+1,S*=p[i],-m);
    for(int j=2;j<=k[i];++j)
        dfs(i+1,S*=p[i],0);
}
inline LL cal(int m,int n){
    int x=n; t=cnt=0; LL ans=0;
    for(int i=1;w[i]*w[i]<=n;++i)
        if(x%w[i]==0){
            p[++t]=w[i]; k[t]=0;
            for(;x%w[i]==0;x/=w[i]) ++k[t];
        }
    if(x>1) p[++t]=x,k[t]=1;
    dfs(1,1,1); LL k;
    sort(d+1,d+1+cnt,c1);
    for(int i=1;i<=cnt;++i) if(d[i].mu)
        for(int j=1;(k=(LL)d[i].d*d[j].d)<=n&&j<=cnt;++j)
            if(n%k==0)
            ans=(ans+(d[i].mu>0?(F(d[i].d,n/k)-F(d[i].d,m/k)):(F(d[i].d,m/k)-F(d[i].d,n/k))))%M;
    return (ans+M)%M;
}        
int main(){
    init(); int T; rd(T);
    for(int n,m;T--;out(cal(m-1,n)*n%M)) rd(m),rd(n);
}    

转载于:https://www.cnblogs.com/Extended-Ash/p/9477084.html

题目 51nod 3478 涉及一个矩阵问题,要求通过最少的操作次数,使得矩阵中至少有 `RowCount` 行和 `ColumnCount` 列是回文的。解决这个问题的关键在于如何高效地枚举所有可能的行和列组合,并计算每种组合所需的操作次数。 ### 解法思路 1. **预处理每一行和每一列变为回文所需的最少操作次数**: - 对于每一行,计算将其变为回文所需的最少操作次数。这可以通过比较每对对称位置的值是否相同来完成。 - 对于每一列,计算将其变为回文所需的最少操作次数,方法同上。 2. **枚举所有可能的行和列组合**: - 由于 `N` 和 `M` 的最大值为 8,因此可以枚举所有可能的行组合和列组合。 - 对于每一种组合,计算其所需的最少操作次数,并取最小值。 3. **计算操作次数**: - 对于每一种组合,需要计算哪些行和列需要修改,并且注意行和列的交叉点可能会重复计算,因此需要去重。 ### 代码实现 以下是一个可能的实现方式,使用了枚举和位运算来处理组合问题: ```python def min_operations_to_palindrome(matrix, row_count, col_count): import itertools N = len(matrix) M = len(matrix[0]) # Precompute the cost to make each row a palindrome row_cost = [] for i in range(N): cost = 0 for j in range(M // 2): if matrix[i][j] != matrix[i][M - 1 - j]: cost += 1 row_cost.append(cost) # Precompute the cost to make each column a palindrome col_cost = [] for j in range(M): cost = 0 for i in range(N // 2): if matrix[i][j] != matrix[N - 1 - i][j]: cost += 1 col_cost.append(cost) min_total_cost = float('inf') # Enumerate all combinations of rows and columns rows = list(range(N)) cols = list(range(M)) from itertools import combinations for row_comb in combinations(rows, row_count): for col_comb in combinations(cols, col_count): # Calculate the cost for this combination cost = 0 # Add row costs for r in row_comb: cost += row_cost[r] # Add column costs for c in col_comb: cost += col_cost[c] # Subtract the overlapping cells for r in row_comb: for c in col_comb: # Check if this cell is part of the palindrome calculation if r < N // 2 and c < M // 2: if matrix[r][c] != matrix[r][M - 1 - c] and matrix[N - 1 - r][c] != matrix[N - 1 - r][M - 1 - c]: cost -= 1 min_total_cost = min(min_total_cost, cost) return min_total_cost # Example usage matrix = [ [0, 1, 0], [1, 0, 1], [0, 1, 0] ] row_count = 2 col_count = 2 result = min_operations_to_palindrome(matrix, row_count, col_count) print(result) ``` ### 代码说明 - **预处理成本**:首先计算每一行和每一列变为回文所需的最少操作次数。 - **枚举组合**:使用 `itertools.combinations` 枚举所有可能的行和列组合。 - **计算成本**:对于每一种组合,计算其成本,并考虑行和列交叉点的重复计算问题。 ### 复杂度分析 - **时间复杂度**:由于 `N` 和 `M` 的最大值为 8,因此枚举所有组合的时间复杂度为 $ O(N^{RowCount} \times M^{ColCount}) $,这在实际中是可接受的。 - **空间复杂度**:主要是存储预处理的成本,空间复杂度为 $ O(N + M) $。 ### 相关问题 1. 如何优化矩阵中行和列的枚举组合以减少计算时间? 2. 在计算行和列的交叉点时,如何更高效地处理重复计算的问题? 3. 如果矩阵的大小增加到更大的范围,如何调整算法以保持效率? 4. 如何处理矩阵中行和列的回文条件不同时的情况? 5. 如何扩展算法以支持更多的操作类型,例如翻转某个区域的值?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值