题意:
对题库有两种操作,一种是在ti时刻加一道题,一种是在ti时刻减一道题拿来比赛,问每道题待在题库里的期望时间。
思路:
从后往前考虑,当前项i为减一道题时,之前的题在这一时刻被取出的概率是1/k,k表示之前还剩多少道题,而在这之后取出的概率就是1-1/k,用sum表示从n到i+1之间某一刻取出的期望时间,那么从n到i某一刻取出的期望时间就是sum*(1-1/k)+1/k*time[i]。
代码:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn=1e5+5;
const int mod=1e9+7;
int a[maxn];
int d[maxn];
LL dp[maxn][32][3];
int sum[32];
LL cal(int n, int m)
{
if(m==0)return 0;
LL res=0;
d[1]=a[1];
memset(sum, 0, sizeof sum);
memset(dp, 0, sizeof dp);
for(int i=2; i<=n; i++)
{
int x=a[i]^a[i-1];
// printf("%d\n", x);
for(int j=0; j<=30; j++)
{
if((x>>j)&1)
{
dp[i][j][0]=dp[i-2][j][1];
dp[i][j][1]=dp[i-2][j][0]+1;
}
else
{
dp[i][j][0]=dp[i-2][j][0]+1;
dp[i][j][1]=dp[i-2][j][1];
}
// printf("%d ", dp[i][j][1]);
}
// printf("\n");
d[i]=d[i-1]^a[i];
if(i>=m+2)
{
int x=d[i]^d[i-m-2];
for(int j=0; j<=30; j++)
{
if((x>>j)&1)
{
dp[i][j][1]--;
}
else dp[i][j][0]--;
}
}
for(int j=0; j<=30; j++)sum[j]+=dp[i][j][1];
}
for(int j=0;j<=30; j++)
{
// printf("%d ", sum[j]);
res=(res+(((1LL<<j)*sum[j])%mod))%mod;
}
// printf("\n");
// printf("%d %lld\n", m, res);
return res%mod;
}
int main()
{
int n, l, r, i, j;
cin>>n>>l>>r;
for(i=1; i<=n; i++)
{
scanf("%d", &a[i]);
}
LL ans=cal(n, r/2*2)-cal(n, (l-1)/2*2);
ans=(ans%mod+mod)%mod;
cout<<ans<<endl;
}

本文介绍了一种计算题库中题目期望时间的方法。通过分析两种操作——添加和移除题目,文章给出了一种从后向前计算每道题在题库中停留期望时间的算法。该算法使用动态规划思想,考虑了题目被抽取的概率变化。
564

被折叠的 条评论
为什么被折叠?



