求问此种方法如何保证求得的f(S,T)最大?

(´∇ノ`*)ノ 2020-12-27 01:21:26
2020安徽省省赛
D. 字符串修改
对于两个由 0 与 1 组成的长度均为 N 的序列 S 和 T,f(S,T)定义如下:
重复如下操作,使得序列 S 与序列 T 相同。f(S,T)是经过操作后,所需要的最少的花
费。
改变 S[i]的值(0 改为 1 或者 1 改为 0),它的花费为 D*C[i],其中 D 是在此操作之前,
序列中满足 S[j]≠T[j]的 j 的个数(1<=j<=N)。C[i]表示对 i 位置进行变换的代价。
对于一个固定长度 N,共有2ே ∗ (2ே − 1)对由 01 组成的序列(S,T),计算所有 f(S,T)
的总和,并输出它对10ଽ + 7的结果。
数据范围
1 ≤ ܰ ≤ 2 ∗ 10ହ
1≤ܥሾ݅ሿ ≤ 10ଽ
输入说明
输入第一行为一个整数 N,表示 S与 T的长度,第二行共 N个整数,C[1],C[2],C[3],…,C[N]。
输出说明
输出一个整数,所有 f(S,T)之和对10ଽ + 7取模的结果。
样例一
输入样例
1
1000000000
输出样例
999999993
样例二
输入样例
2
5 8
输出样例
124
提示
对样例 1,S 可取 0、1,T 可取 0、1,共有 f(0,0),f(0,1),f(1,0),f(1,1)四种情况
f(0,0)=0,f(1,1)=0,f(1,0)=f(0,1)=10^9,故最终结果为 2*10^9, 取模可得 999999993。
样例 2 中,针对 S=(0,1),T=(1,0)这个序列对,首先将 S1 改为 1,造成的花费为 5*2=10,
因为 S1 与 T1,S2 与 T2 均不相同。再将 S2 改为 0,造成的花费为 8*1=8,故 f(S,T)=18。

解法:运用数学方法
通过一些数学方法对题目要求进行求解,首先求逆元是为了算组合Cn,m。通过快速幂的方法计算2的n次方。然后通过数学的方法,从第一位开始,有四种状态,两种相等两种不等,当状态不等的时候开始计算花费,后面n-1个数,人选m个不等,即为Cn-1,m,共两种状态,即2^m。
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;

typedef long long LL;
const LL maxn(200005), mod(1e9 + 7);
LL Jc[maxn];

void calJc() //求maxn以内的数的阶乘
{
Jc[0] = Jc[1] = 1;
for(LL i = 2; i < maxn; i++)
Jc[i] = Jc[i - 1] * i % mod;
}

//费马小定理求逆元
LL pow(LL a, LL n, LL p) //快速幂 a^n % p
{
LL ans = 1;
while(n)
{
if(n & 1) ans = ans * a % p;
a = a * a % p;
n >>= 1;
}
return ans;
}

LL niYuan(LL a, LL b) //费马小定理求逆元
{
return pow(a, b - 2, b);
}

LL C(LL a, LL b) //计算C(a, b)
{
if(a < b) return 0;
return Jc[a] * niYuan(Jc[b], mod) % mod
* niYuan(Jc[a - b], mod) % mod;
}


//快速幂
LL poww(int a,int b){
LL ans=1,base=a;
while(b!=0){
if(b&1!=0)
ans=ans*base%mod;
base=base*base%mod;
b>>=1;
}
return ans;
}

LL d[maxn]; //存放D数据
LL a[maxn]; //存放需要乘以多少次D[i]

int main()
{
calJc();//初始化
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>d[i];
}

for(int i=1;i<=n;i++)
{
LL a1,a2,a3=0;
a1=poww(4,i-1);
a2=poww(2,n-i+1);
a[i]=a1*a2%mod;
for(int k=0;k<=n-i;k++)
{
a3=a3+C(n-i,k)*(k+1)%mod;
a3=a3%mod;
}
a[i]=a[i]*a3%mod;
}

LL ans=0;
for(int i=1;i<=n;i++)
{
ans=ans+a[i]*d[i]%mod;
}
cout<<ans<<endl;
return 0;
}
...全文
129 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
maguangzhi 2020-12-29
  • 打赏
  • 举报
回复
这个应该先求最小编辑距离,或者最大公共子串。然后再求代价。参见我的资源下载:https://mp.csdn.net/console/upDetailed

64,649

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧