zoukankan      html  css  js  c++  java
  • CF986F Oppa Funcan Style Remastered 题解

    Codeforces
    Luogu
    欸嘿嘿

    Description.

    求是否存在序列 \(\{b_i\}\) 使得 \(\forall i,b_i|B\)\(\sum_{i}b_i=A\)
    \(A\le 10^{18}\)\(B\le 10^{15}\) 且保证本质不同的 \(B\) 不超过 \(50\) 个,\(Ca\le 10^4\)

    Solution

    以为只需要考虑两个,结果根本不对。
    首先考虑分解 \(B\) 的质因数,暴力即可,发现复杂度很正确。
    然后,如果 \(B=1\) 特判,如果 \(B\in\text{Prime}\) 直接特判。
    \(\text{Fac}(x)\) 表示 \(x\) 所有质因数构成的集合。
    如果 \(|\text{Fac}(x)|=2\),直接做,因为可以直接算出 \(aF_1+bF_2=A\) 的解调一下即可。
    然后,剩下的如果 \(|\text{Fac}(x)|>2\),那 \(\exists a\in\text{Fac}(x),a\le 10^{5}\)
    数据范围变小了,发现可以同余最短路,直接做就可以了。
    复杂度 \(O(\frac{\sqrt V}{\ln V}\times 50+\sqrt[3]V\times\log V)\)
    前面是质因数分解的复杂度,后面是同余最短路的复杂度,直接写 SPFA 即可。

    Coding.

    点击查看Shit代码
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	f?x=-x:x;
    }
    template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}/*}}}*/
    int wt,ln[55],qu[1000005];ll q[55],vl[55][105],ds[55][500005];char vs[500005];
    const int N=31622779;int pr[1951959],pc;char pv[N];//prinit{{{
    inline void prinit(int n=N-1)
    {
    	pv[1]=1;for(int i=1;i<=n;i++)
    	{
    		if(!pv[i]) pr[++pc]=i;
    		for(int j=1;j<=pc&&i*pr[j]<=n;j++) {pv[i*pr[j]]=1;if(i%pr[j]==0) break;}
    	}
    }//}}}
    inline int ksm(int x,int q,int P) {int r=1;for(;q;q>>=1,x=1ll*x*x%P) if(q&1) r=1ll*r*x%P;return r;}
    inline char chk(ll a,ll b,ll v)
    {
    	if(1.0L*a*b-a-b<v) return 1;//ax+by=v,by%a=v%a
    	if(a==2) return v%2==0||((b&1)&&v>=b);//y=v*(b^-)%a
    	ll y=1ll*v%a*ksm(b%a,a-2,a)%a,x=(v-b*y)/a;
    	if(a*x+b*y!=v) return 0;else return x>=0;
    }
    inline void init(ll b)
    {
    	++wt;ll *f=vl[wt],*d=ds[wt];q[wt]=b;
    	for(register int i=1;1ll*pr[i]*pr[i]<=b;i++)
    		if(b%pr[i]==0) {f[++ln[wt]]=pr[i];while(b%pr[i]==0) b/=pr[i];}
    	int hd=1,tl=1;if(b!=1) f[++ln[wt]]=b;
    	if(ln[wt]<=2) return;else memset(vs,0,f[1]+1),sort(f+1,f+ln[wt]+1);
    	int P=f[1];memset(d,0x3f,(P+1)<<4),d[0]=0,qu[1]=0;
    	//for(int i=1;i<=ln[wt];i++) printf("%lld%c",f[i],i==ln[wt]?'\n':' ');
    	while(hd<=tl)
    	{
    		int x=qu[hd++];vs[x]=0;
    		for(int i=2;i<=ln[wt];i++)
    		{
    			int y=(x+f[i])%P;if(d[y]>d[x]+f[i])
    				{d[y]=d[x]+f[i];if(!vs[y]) vs[y]=1,qu[++tl]=y;}
    		}
    	}
    	//for(int i=0;i<P;i++) printf("%lld%c",d[i],i==P-1?'\n':' ');
    }
    inline void solve()
    {
    	ll a,b,*f,*d;read(a),read(b);int n=0;if(b==1) return puts("NO"),void();
    	for(int i=1;i<=wt;i++) if(q[i]==b) f=vl[i],n=ln[i],d=ds[i];
    	if(!n) init(b),n=ln[wt],d=ds[wt],f=vl[wt];
    	if(n==1) return puts(a%b==0?"YES":"NO"),void();
    	if(n==2) return puts(chk(f[1],f[2],a)?"YES":"NO"),void();
    	//for(int i=0;i<f[1];i++) printf("%lld%c",d[i],i==f[1]-1?'\n':' ');
    	int P=f[1];if(d[a%P]<=a) puts("YES");else puts("NO");
    }
    int main() {int Ca;for(prinit(),read(Ca);Ca--;) solve();return 0;}
    
  • 相关阅读:
    Android开源图表图形库K线图
    交易所8种作死方式
    Android百大框架排行榜
    15类Android通用流行框架
    如何避免Scrum敏捷开发团队反思会形式化,海星法介绍
    2018年Android面试题含答案--适合中高级
    FCoin优势
    golang学习笔记16 beego orm 数据库操作
    金融系统中加密机的简介
    ESB(Enterprise Service Bus)企业服务总线介绍
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15210929.html
Copyright © 2011-2022 走看看