• 《HDU 2020 多校 第一场》


    1005 :

    Fibonacci Sum

    从斐波那契的通项入手。

    思路:

     

    所以 $ans =  \sum_{i = 0}^{n} ans1^k = \sum_{i = 0}^{n} \frac{1}{T^k} (b^i-c^i)^k$

    令$f[i] = (b^i-c^i)^k$

    那么ans = $\frac{1}{T^k} * \sum_{i = 0}^{n} f[i]$

    首先对f[i]二项式展开,然后求和合并之后。

    可以发现$sum = C(k,0) *(-1)^k( (a^0)^0*(b^0)^k+(a^1)^0*(b^1)^k +....)+C(k,1)... $

    对于C(k,i)里的每一项是一个等比数列的求和。

    那么可以O(1)求出。最后枚举k去算总和即可

     由于这里常数过大,所以先预处理一下逆元。

    同时由于n稍微大了些。

    所以通过欧拉降幂公式,因为模数为质数。

    a^b % p = a^(b % (p-1)) % p

    然后因为C(k,i)之间公比是乘a/b倍的,所以不需要每次都快速幂求公比。

    只需要前面的公比*a/b即可。

    还有当公比为1时中间等比数列求和的分母为0,这时不用求和公式,直接可以发现其中每项都是1,那么求和就是n

    Code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef long double ld;
    typedef pair<int,int> pii;
    const int N = 1e5+5;
    const LL Mod = 1e9+9;
    #define pi acos(-1)
    #define INF 1e8
    #define INM INT_MIN
    #define dbg(ax) cout << "now this num is " << ax << endl;
    LL a = 691504013,b = 308495997,d = 383008016;
    LL f[N],inv[N];
    inline LL read()
    {
         LL x = 0,f = 1;char c = getchar();
         while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
         while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
         return x*f;
    }
    LL quick_mi(LL a,LL b)
    {
         LL re = 1;
         a %= Mod;
         while(b)
         {
              if(b&1) re = (re*a)%Mod;
              a = (a*a)%Mod;
              b >>= 1;
         }
         return re;
    }
    void init()
    {
         f[0] = 1;
         for(int i = 2;i < N;++i) f[i] = f[i-1]*i%Mod;
         inv[N-1] = quick_mi(f[N-1],Mod-2);
         for(int i = N-2;i >= 0;--i) inv[i] = inv[i+1]*(i+1)%Mod;
    }
    LL C(LL n,LL m)
    {
         return f[n]*inv[m]%Mod*inv[n-m]%Mod;
    }
    LL slove(LL n,LL c,LL k)
    {
         LL A = quick_mi(a,c%(Mod-1)),B = quick_mi(b,c%(Mod-1));
         LL aa = 1,bb = quick_mi(B,k),tmp = quick_mi(B,Mod-2);//预处理第一项公比
         LL ans = 0;
         for(LL i = 0;i <= k;++i)
         {
              LL x = aa*bb%Mod;//求出公比
              LL ma = C(k,i);
              LL sum = x*(quick_mi(x,n%(Mod-1))-1+Mod)%Mod*quick_mi(x-1,Mod-2)%Mod;//等比数列求和
              if(x == 1) sum = n%Mod;//公比为1时
              if((k-i) & 1) ans = (ans-ma*sum%Mod)%Mod;//-1是偶次还是幂次
              else ans = (ans+ma*sum%Mod)%Mod;
              aa = aa*A%Mod*tmp%Mod;//公比递推
         }
         LL ta = quick_mi(d,Mod-2);
         ans = ans*quick_mi(ta,k)%Mod;
         ans = (ans%Mod+Mod)%Mod;
         return ans;
    }
    int main()
    {
         init();
         int t;t = read();
         while(t--)
         {
              LL n,c,k;
              n = read(),c = read(),k = read();
              LL ans = slove(n,c,k);
              printf("%lld\n",ans);
         }
       //  system("pause");
         return 0;
    }
    View Code

    1009:

    Leading Robots

    思路:

    有非常多的解法。

    1:

    我们知道x = x0+1/2 a*t*2.

    那么以t^2为横坐标,x为纵坐标来建xoy坐标系。

    那么先按x坐标来排序,之后我们从下往上扫,来判断每条直线是否可以成为领队,同时用一个单调栈来维护领队

    当当前直线的a >= 栈顶直线的a时,显然在他右边的而且a还大于它,那么栈顶元素不可能成为领队,所以栈顶出栈。

    否则判断当前直线与栈顶相遇 的时间是否  <= 栈顶元素和栈内栈下一个元素的相遇时间。如果是,那么显然在栈顶元素成为领队前就会被当前直线超到。那么栈顶出栈。

    注意的是时间是t^2,然后用mp来维护一下重复的点,有重合那么该点不可能为领队。

    2.形象理解。

    将所有元素按加速度升序。同样单调栈来维护领队。

    对于当前,那么显然之后的元素a 都 >= 栈顶。

    如果这时当前元素的 x >= 栈顶元素。同样的栈顶出栈

    那么只需要判断 当前元素遇到栈顶的时间是否 <= 栈顶 与栈内栈顶下一个相遇的时间。满足则出栈。

    Code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef long double ld;
    typedef pair<int,int> pii;
    const int N = 5e4+5;
    const int Mod = 1e9+9;
    #define pi acos(-1)
    #define INF 1e8
    #define INM INT_MIN
    #define dbg(ax) cout << "now this num is " << ax << endl;
    struct Node{
         LL x,a;
         friend bool operator < (const Node &a,const Node &b) 
         {
              if(a.a == b.a) return a.x < b.x;
              return a.a < b.a;
         }
    }f[N];
    bool check(Node a,Node b,Node c)
    {
         return (a.x-b.x)*(c.a-b.a)-(b.x-c.x)*(b.a-a.a) <= 0;
    }
    int q[N];
    int main()
    {
         int t;scanf("%d",&t);
         while(t--)
         {
              int n;scanf("%d",&n);
              map<Node,int> mp;
              for(int i = 1;i <= n;++i) 
              {
                   scanf("%lld %lld",&f[i].x,&f[i].a);
                   mp[f[i]]++;
              }
              sort(f+1,f+n+1);
              int cnt = 0;
              for(int i = 1;i <= n;++i)
              {
                   while((cnt > 0 && f[i].x >= f[q[cnt]].x) || (cnt > 1 && check(f[i],f[q[cnt]],f[q[cnt-1]]))) cnt--;
                   q[++cnt] = i;
              }
              int ans = 0;
              for(int i = 1;i <= cnt;++i)
              {
                   if(mp[f[q[i]]] == 1) ans++;//这里是栈内的元素判重,少些了q调了好久
              }
              printf("%d\n",ans);
         }
         system("pause");
         return 0;
    }
  • 相关阅读:
    <<浪潮之巅>>阅读笔记三
    <<浪潮之巅>>阅读笔记二
    <<浪潮之巅>>阅读笔记一
    《需求工程——软件建模与分析》阅读笔记三
    个人总结
    学习进度条(第十六周)
    人月神话阅读笔记03
    第十五周学习进度条
    人月神话阅读笔记02
    操作
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/13360603.html
Copyright © 2020-2023  润新知