• $SNOI2019$数论


    一本正经的链接(SNOI2019)数论

    有环的东西真(TM)难调……

    暴力显然是跑一遍(T),对每个数判断一下。

    考虑转化研究对象,变为对于每一个(A[i])有多少(x)满足(0< x< T)(xequiv A[i]mod P)(x mod Qin B)

    显然可令(x=A[i]+k*P),枚举(k),考虑(k)的上界:取到(left lfloor frac{T-1-A[i]}{P} ight floor)。我们发现(x)肯定会在(mod Q)意义下循环。

    其一定在(k*Pequiv 0mod Q)时循环。这样我们可以的得到循环节为(k=frac{Q}{gcd(P,Q)})

    这样我们就可以处理出环,在环上跑(left lfloor frac{T-1-A[i]}{P} ight floor)步,看有多少点可以产生贡献(重复经过也要算贡献)。

    拿前缀和维护即可,因为((x+P)\%Q)不好倒回,所以我的前缀和和常用的不太一样。

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    inline int read()
    {
        int f=1,w=0;char x=0;
        while(x<'0'||x>'9') {if(x=='-') f=-1; x=getchar();}
        while(x!=EOF&&x>='0'&&x<='9') {w=(w<<3)+(w<<1)+(x^48);x=getchar();}
        return w*f;
    }
    const int N=1000010;
    int A[N],B[N],Fab[N];
    int Col[N],Id[N],S[N];
    int P,Q,n,m,T,Cnt,ans;
    vector<int> Cir[N],Sum[N];
    inline int gcd(int a,int b) {return b?gcd(b,a%b):a;}
    signed main(){
    #ifndef ONLINE_JUDGE
        freopen("A.in","r",stdin);
    #endif
    	P=read(),Q=read(),n=read(),m=read(),T=read();
    	for(int i=1;i<=n;i++) A[i]=read();
    	for(int i=1;i<=m;i++) B[i]=read();
    	if(P>Q) swap(A,B),swap(n,m),swap(P,Q);
    	for(int i=1;i<=m;i++) Fab[B[i]]=1;
    	int Len=Q/gcd(P,Q);sort(A+1,A+n+1);
    	for(int i=0;i<Q;i++)
    		if(!Col[i])
    		{
    			int Tot=0;Col[i]=++Cnt,Id[i]=0;
    			for(int j=(i+P)%Q;j!=i;j=(j+P)%Q) Id[j]=++Tot,Col[j]=Col[i];
    			Sum[Col[i]].push_back(0);
    			for(int j=i;(j+P)%Q!=i;j=(j+P)%Q) Sum[Col[i]].push_back(Sum[Col[i]][Id[j]]+Fab[j]);
    			for(int j=(i+P)%Q;j!=i;j=(j+P)%Q) S[Col[i]]+=Fab[j];S[Col[i]]+=Fab[i];
    			Cir[Col[i]].push_back(i);
    			for(int j=(i+P)%Q;j!=i;j=(j+P)%Q) Cir[Col[i]].push_back(j);
    		}
    	for(int i=1;i<=n;i++)
    	{
    		int Stp=floor((T-A[i]-1)/P*1.0);
    		ans+=Stp/Len*S[Col[A[i]]];Stp%=Len;
    		if(Stp+Id[A[i]]<Len)
    		{
    			int End=Cir[Col[A[i]]][Stp+Id[A[i]]];
    			ans+=Sum[Col[A[i]]][Id[End]]-Sum[Col[A[i]]][Id[A[i]]]+Fab[End];
    		}
    		else
    		{
    			int End=Cir[Col[A[i]]][(Stp+Id[A[i]])%Len];
    			ans+=S[Col[A[i]]]-Sum[Col[A[i]]][Id[A[i]]]+Sum[Col[A[i]]][Id[End]]+Fab[End];
    		}
    	}
    	printf("%lld",ans);
    }
    
  • 相关阅读:
    正则表达式(二):Unicode诸问题(上)
    ANT Notes
    Linux下OpenGL开发 -- 准备篇 (转)
    两个和尚
    Office 2008 for Mac 安装笔记
    从软件工程师到IT猎头:我的一点经历和感触 (转)
    One splitpath implementation (platform independent)
    ANT的使用(转)
    80后中专毕业奋斗10年 我的理财选择
    用ANT来实现邮件发送
  • 原文地址:https://www.cnblogs.com/wo-shi-zhen-de-cai/p/11637766.html
Copyright © 2020-2023  润新知