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

    一、题目

    点此看题

    二、解法

    话说很多题都想了同余最短路,今天终于用上一回了。

    首先可以暴力预处理 (sqrt k) 以内的质因数然后对 (k) 搞质因数分解,其它因数可以被质数之和表示所以没用。

    然后跑同余最短路即可,时间复杂度是 (O()最小质因数(cdotlog)),我们可以通过讨论来降低复杂度。如果质因数个数 (=1) 直接判断是否为倍数,(=2) 相当于判断二元一次方程有无解,否则最小值因数 (leq sqrt[3]{k})

    那么时间复杂度 (O(50cdot sqrt[3]kcdot log+sqrt k))

    三、总结

    同余最短路的模型就是无限选若干个数,问能不能凑出某个数(/)某个数以内能凑出数的个数。

    如果复杂度和定和(/)定乘积的量有关,可以通过小范围讨论来大幅降低复杂度。

    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <queue>
    #include <map>
    using namespace std;
    const int M = 33000005;
    const int N = 100005;
    bool vis[M];int cnt,p[M];
    #define int long long
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int m,k,dis[N],a[N],ans[N],in[N];
    struct node{int n,id;};map<int,vector<node>> mp;
    void init(int n)
    {
    	for(int i=2;i<=n;i++)
    	{
    		if(!vis[i]) p[++cnt]=i;
    		for(int j=1;j<=cnt && i*p[j]<=n;j++)
    		{
    			vis[i*p[j]]=1;
    			if(i%p[j]==0) break;
    		}
    	}
    }
    void dec(int n)
    {
    	k=0;
    	for(int i=1;i<=cnt && p[i]*p[i]<=n;i++)
    		if(n%p[i]==0)
    		{
    			a[++k]=p[i];
    			while(n%p[i]==0) n/=p[i];
    		}
    	if(n>1) a[++k]=n;
    }
    int qkpow(int a,int b,int m)
    {
    	int r=1;a%=m;
    	while(b>0)
    	{
    		if(b&1) r=r*a%m;
    		a=a*a%m;
    		b>>=1;
    	}
    	return r;
    }
    void work(int x,vector<node>&v)
    {
    	dec(x);
    	if(x==1) return ;
    	if(k==1)
    	{
    		for(auto t:v)
    			ans[t.id]=t.n%a[k]?0:1;
    		return ;
    	}
    	if(k==2)
    	{
    		for(auto t:v)
    		{
    			int k=t.n%a[1]*qkpow(a[2],a[1]-2,a[1])%a[1];
    			ans[t.id]=k*a[2]<=t.n;
    		}
    		return ;
    	}
    	queue<int> q;
    	memset(dis,0x3f,sizeof dis);
    	dis[0]=0;q.push(0);in[0]=1;
    	while(!q.empty())
    	{
    		int u=q.front();q.pop();
    		in[u]=0;
    		for(int i=2;i<=k;i++)
    		{
    			int v=(u+a[i])%a[1];
    			if(dis[v]>dis[u]+a[i])
    			{
    				dis[v]=dis[u]+a[i];
    				if(!in[v]) q.push(v),in[v]=1;
    			}
    		}
    	}
    	for(auto t:v)
    		ans[t.id]=dis[t.n%a[1]]<=t.n;
    }
    signed main()
    {
    	m=read();init(33000000);
    	for(int i=1;i<=m;i++)
    	{
    		int x=read(),y=read();
    		mp[y].push_back(node{x,i});
    	}
    	for(auto tmp:mp) work(tmp.first,tmp.second);
    	for(int i=1;i<=m;i++)
    		puts(ans[i]?"YES":"NO");
    }
    
  • 相关阅读:
    【PBR的基本配置】
    【super vlan的配置】
    Day_03-函数和模块的使用
    Day_02-Python的循环结构
    Day_02-Python的分支结构和循环结构
    Day01_课后练习题
    Day01_初识Python
    一、Linux知识体系结构图
    NAND Flash结构及驱动函数
    区分大端和小端
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/15218925.html
Copyright © 2011-2022 走看看