zoukankan      html  css  js  c++  java
  • [HDU-6847] Decision (2020多校7T4)(类欧几里得问题)

    [HDU-6847] Decision (2020多校7T4) (类欧几里得问题)

    枚举(|v_1-v_2|)后,可以递推,用含首项((v_1+v_2))的一次函数表示函数值为(a(v_1+v_2)+b),则问题等价于求

    (egin{aligned} sum_{i=0}^n [2|(ai+b)mod m] end{aligned}) ,其中 (n) 对于每个 (v_1-v_2) 是不同的

    这个问题,可以转化为一个简单的类欧几里得问题

    ((ai+b)mod m mod 2= ((ai+b)-(mmod 2)cdot lfloor frac{ai+b}{m} floor )mod 2)

    这个式子即把每次被(m)取模减少的(m)算进贡献

    可以看到操作非常简单,可以直接套上万能欧几里得的板子

    当然,也可以对于(m)的各种情况讨论,转化为求(lfloor frac{ai+b}{m} floor),其主要思想还有应用 (xmod 2=x-2cdot lfloor frac{x}{2} floor) 的转化

    我比赛时去抄了自己的类欧几里得模板

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
    #define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
    
    char IO;
    template <class T=int> T rd(){
        T s=0; int f=0;
        while(!isdigit(IO=getchar())) if(IO=='-') f=1;
        do s=(s<<1)+(s<<3)+(IO^'0');
        while(isdigit(IO=getchar()));
        return f?-s:s;
    }
    
    const int N=1e6+10;
    
    int t,a,c,m;
    int fx[N],fy[N];
    
    ll gcd(ll a,ll b){ return b==0?a:gcd(b,a%b); }
    
    ll D2(ll n){
        return n*(n+1)/2;
    }
    ll F(ll a,ll b,ll c,ll n){
        if(n<0) return 0;
        if(a==0) return (b/c)*(n+1);
        if(a>=c || b>=c) {
            ll ans=F(a%c,b%c,c,n)+D2(n)*(a/c)+(n+1)*(b/c);
            return ans;
        }
        ll t=(a*n+b)/c;
        ll ans=t*n-F(c,-b+c-1,a,t-1);
        return ans;
    }
    
    ll CalcMod(int a,int b,int m,int n){
        return F(a,b,m,n)-F(a,b,m*2,n)*2;
    }
    
    ll Calc(int a,int b,int n){
        // for i= [l,r] (ax+b) %m %2
        if(~m&1){
            // (ax+b)%2;
            a%=2,b%=2;
            if(a==0) return b*(n+1);
            return (n+1+b)/2;
        } else {
            // (ax+b) %m %2 = ((ax+b)/m + ax+b)%2
            int c=a%2,d=b%2;
            if(c==0) {
                // =((ax+b)/m+b)%2;
                if(d==0) return CalcMod(a,b,m,n);
                else return (n+1)-CalcMod(a,b,m,n);
            } else {
                // (ax+b) %m %2 = ((ax+b)/m + (x&1)+d)%2
                ll ans=0;
    
                // i%2 == 0
                ll t=CalcMod(a*2,b,m,n/2);
                if(d) t=n/2+1-t;
                ans+=t;
    
                b+=a;
                // i%2 == 1
                n--;
                if(n<0) return ans;
                t=CalcMod(a*2,b,m,n/2);
                if(!d) t=n/2+1-t;
                ans+=t;
                return ans;
            }
        }
    }
    
    int main(){
        rep(kase,1,rd()) {
            t=rd(),a=rd(),c=rd(),m=rd();
            fx[0]=1,fy[0]=0;
            rep(i,1,t) fx[i]=1ll*fx[i-1]*a%m,fy[i]=(1ll*fy[i-1]*a+c)%m;
            ll ans=0;
            rep(i,0,t) {
                if(i==0) {
                    ans+=Calc(fx[i]*2%m,fy[i],t);
                } else {
                    // a<b, b - a = i
                    // a=[0,m-i]
                    // b=[i,m]
                    ll tmp=(1ll*i*fx[i]+fy[i])%m;
                    ans+=Calc(fx[i]*2%m,tmp,t-i)*2;
                }
            }
            ll tmp=1ll*(t+1)*(t+1);
            ans=tmp-ans;
            ll g=gcd(tmp,ans);
            printf("%lld/%lld
    ",ans/g,tmp/g);
        }
    }
    
  • 相关阅读:
    Java实现 蓝桥杯 算法训练 画图(暴力)
    Java实现 蓝桥杯 算法训练 画图(暴力)
    Java实现 蓝桥杯 算法训练 相邻数对(暴力)
    Java实现 蓝桥杯 算法训练 相邻数对(暴力)
    Java实现 蓝桥杯 算法训练 相邻数对(暴力)
    Java实现 蓝桥杯 算法训练 Cowboys
    Java实现 蓝桥杯 算法训练 Cowboys
    55. Jump Game
    54. Spiral Matrix
    50. Pow(x, n)
  • 原文地址:https://www.cnblogs.com/chasedeath/p/13485442.html
Copyright © 2011-2022 走看看