中超7 hdu 7048 Link with EQ (DP,手模数据推规律,转换,思维)

49 篇文章 1 订阅
30 篇文章 1 订阅

hdu 7048 Link with EQ

题意:
  • 一条长桌有 n n n 个座位

    1 1 1 个同学随机选 1 1 1 个位置坐下

    接下来的同学,选 1 1 1 个离最近同学的距离最大的位置坐下

    (choose a position whose shortest distance to other students is maximized. 这句话要多看几遍,防止读假题)

    当最远距离为 1 1 1 时(即再坐 1 1 1 个同学会有相邻的情况出现),称桌子满了

    求桌子满时,同学数的期望

分析:
  • 要求的是期望,那肯定要知道所有的情况

    对于这种题目,只看题目描述看不出花来(大佬是能一眼看出法,而我蒟蒻一个…),因此我去手模了 n = 1 n=1 n=1 n = 8 n=8 n=8 的情况(手动打表找规律),发现了规律所在:第 1 1 1 个人的位置定下来之后,剩下的人的位置就确定了 (两人之间位置数为偶数的情况,看上去有两种,其实是一样的)

    所以问题就转换成了,枚举第 1 1 1 个人选 1 − − n 1--n 1n​​ 不同的位置的贡献值并求和,最后输出的是期望对 1 e 9 + 7 1e9+7 1e9+7 模逆

    (It can be proved that the a n s w e r answer answer can always be represented as p q \frac{p}{q} qp , where the greatest common factor between p p p and q q q is 1. When outputting the a n s w e r answer answer modulo M M M , you should output such an integer x x x that 0 ≤ x < M 0≤x<M 0x<M and x ⋅ q ≡ p ( m o d M x⋅q≡p(mod M xqp(modM). 这句话是说答案要对 M M M 求模逆)

    • 讲一下如何快速求出n在不同位置的贡献值

      d p i dp_i dpi 表示在两边都有人,中间位置数为 i i i 时的方案数

      m i d = ( i + 1 ) / 2 mid=(i+1)/2 mid=(i+1)/2 d p i = d p m i d − 1 + d p i − m i d + 1 dp_i = dp_{mid-1}+dp_{i-mid}+1 dpi=dpmid1+dpimid+1

      这个状态转移比较好理解,脑模一下,位置数为 i + 2 i+2 i+2 的长桌,现在 1 1 1 i + 2 i+2 i+2 都坐了人,再去一人,那他必定坐在 ( 1 + i ) / 2 (1+i)/2 (1+i)/2 的位置

      现在我们来手模规律所在了,令 n = 8 n=8 n=8 ,第 1 1 1 个人坐在i位置桌子满时的贡献值分别为:

      1. d p 6 + 2 dp_6+2 dp6+2
      2. d p 5 + 2 dp_5 +2 dp5+2
      3. d p 4 + 3 dp_4 +3 dp4+3
      4. d p 3 + 3 dp_3 + 3 dp3+3
      5. d p 3 + 3 dp_3 +3 dp3+3
      6. d p 4 + 3 dp_4 +3 dp4+3
      7. d p 5 + 2 dp_5 +2 dp5+2
      8. d p 6 + 2 dp_6 +2 dp6+2

      发现了吧(若没发现,再多模几个数)

      用前缀和 s [ i ] s[i] s[i]​ 维护一下 d p dp dp​ ,那么总的贡献值 a n s = 2 s [ n − 2 ] + 3 n − 4 ans=2s[n-2]+3n-4 ans=2s[n2]+3n4

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N=1e6+5, mo=1e9+7;
int binpow(int a,int b=mo-2,int p=mo)
{
    int ans=1;
    while(b)
    {
        if(b&1) ans = ans*a%p;
        a = a*a%p;
        b >>= 1;
    }
    return ans;
}
int dp[N], s[N];
signed main()
{
    ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
    for(int i=3;i<=N-5;i++)
    {
        int mid = (1+i)>>1;
        dp[i] = dp[mid-1]+dp[i-mid]+1;
        s[i] = (s[i-1]+2*dp[i])%mo;
    }
    int T;
    cin>>T;
    while(T--)
    {
        int n;
        cin>>n;
        if(n<=2) { cout<<"1"<<endl; continue; } // 2*binpow(2)%mo
        if(n==3) { cout<<"666666673"<<endl; continue; } // 5*binpow(3)%mo
        int ans = (s[n-2]+3*n-4)%mo;
        ans = ans*binpow(n)%mo;
        cout<<ans<<endl;
    }

    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yezzz.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值