zoukankan      html  css  js  c++  java
  • [SNOI2019]数论

    https://www.luogu.org/problemnew/show/P5330

    题解

    我们要求有多少个x满足:

    [x=a_i+P*k_1=b_j+Q*k_2 ]

    然后移一下:

    [a_i+P*k_1=b_j (mod Q) ]

    可以发现这个东西是有循环节的。

    可以发现它的循环周期是(lcm(P,Q))

    那么我们需要求的是对于每个(a_i),它在长度为(Q)的环上走,能碰到几个(B)

    直接算就可以了。

    代码

    #include<bits/stdc++.h>
    #define N 1000009
    using namespace std;
    typedef long long ll;
    ll q,p,n,m,t,a[N],b[N],sum[N],rk[N],ans,be[N],num[N];
    bool vis[N];
    inline ll rd(){
    	ll x=0;char c=getchar();bool f=0;
    	while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	return f?-x:x;
    }
    inline ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
    inline ll lcm(ll x,ll y){return x/gcd(x,y)*y;}
    int main(){
    	p=rd();q=rd();n=rd();m=rd();t=rd();t--;
    	for(int i=1;i<=n;++i)a[i]=rd();
    	for(int i=1;i<=m;++i)b[rd()]=1;
    	for(int i=0;i<q;++i)if(!vis[i]){
    		int xx=i;
    		int cnt=0,last=-1;
    		while(1){
    			vis[xx]=1;
    			rk[xx]=++cnt;be[xx]=i;
    			if(last>=0)sum[xx]+=sum[last];
    			sum[xx]+=b[xx];
    			last=xx;
    			xx=(xx+p)%q;
    			if(vis[xx])break;
    		}
    		num[i]=sum[last];
    	}
    	ll len=lcm(q,p);
    	for(int i=1;i<=n;++i)if(a[i]<=t){
    		ll le=t-a[i],id=a[i]%q;
    		ans+=(le/len)*num[be[id]];le%=len;le/=p;
    		ll yy=(id+le*p)%q;
    		if(rk[yy]>=rk[id])ans+=sum[yy]-sum[id]+b[id];
    		else ans+=num[be[id]]-sum[id]+b[id]+sum[yy];
    	}
    	cout<<ans;
    	return 0;
    }
    
  • 相关阅读:
    题解45 跳跃游戏 II
    《重构》第八章阅读总结
    Scala学习笔记一
    Java初学随笔
    染色算法总结
    BingMap
    Google Earth API 替换方案
    本周安排
    OleDb 内存泄露问题
    css3 布局
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/10821574.html
Copyright © 2011-2022 走看看