zoukankan      html  css  js  c++  java
  • 联考20200607 T1 随机除法

    题目:


    分析:
    啊,范围是(1e24),出题人身体健康冚家富贵嗷
    不敢用__int128,手写高精度(
    考虑(N=prod_{i=1}^{m}p_i^{k_i})
    不难发现最后的答案只与(k)有关,尝试期望(dp)

    前缀和优化一下
    状态(K)由状态(K')转来,(K)(K')只有一位差距1
    我们暴力搜索最大的状态,明显是由最小的质数构成,且(N)最多只会有20个质因数
    两个状态如果排序后相同,这两个状态的值就会相同(每一位等价)
    直接将搜索出来的状态哈希或者直接加入map查询
    然后就暴力预处理所有状态了
    复杂度玄学,不过爆搜出的状态数级别是(1e5),预处理卡着时间过(

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<iostream>
    #include<map>
    #include<bitset>
    #include<string>
    
    #define maxn 200005
    #define K 20
    #define MOD 1000000007
    #define maxm 105
    
    using namespace std;
    
    const long long D=1000000ll*1000000ll;
    
    inline long long getint()
    {
    	long long num=0,flag=1;char c;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    	return num*flag;
    }
    
    map<int,int>M;
    int ans[maxn],sum[maxn][21];
    int cnt,tot,pri[maxm],f[maxm];
    char s[maxm];
    inline bool cmp(int x,int y){return x>y;}
    inline int upd(int x){return x<MOD?x:x-MOD;}
    struct BIGNUM{
    	long long p[2];
    	inline void getnum(long long x)
    	{p[0]=p[1]=0,p[0]=x/D,p[1]=x%D;}
    	friend BIGNUM operator *(BIGNUM x,long long y)
    	{
    		x.p[0]*=y,x.p[1]*=y,x.p[0]+=x.p[1]/D,x.p[1]%=D;
    		return x;
    	}
    	friend bool operator <(BIGNUM x,BIGNUM y)
    	{
    		return x.p[0]==y.p[0]?x.p[1]<y.p[1]:x.p[0]<y.p[0];
    	}
    	friend bool operator <=(BIGNUM x,BIGNUM y)
    	{
    		return x.p[0]==y.p[0]?x.p[1]<=y.p[1]:x.p[0]<y.p[0];
    	}
    	friend BIGNUM operator /(BIGNUM x,long long y)
    	{
    		x.p[1]+=x.p[0]%y*D,x.p[0]/=y,x.p[1]/=y;
    		return x;
    	}
    	friend long long operator %(BIGNUM x,long long y)
    	{
    		x.p[1]+=x.p[0]%y*D;
    		return x.p[1]%y;
    	}
    }N;
    pair<BIGNUM,vector<int> >p[maxn];
    vector<int>d;
    
    inline int ksm(int num,int k)
    {
    	int ret=1;
    	for(;k;k>>=1,num=1ll*num*num%MOD)if(k&1)ret=1ll*ret*num%MOD;
    	return ret;
    }
    inline int solve(vector<int>a,int p)
    {
    	while(p<K&&a[p]<a[p+1])swap(a[p],a[p+1]),p++;
    	int ans=0;
    	for(int i=0,sz=a.size();i<sz;i++)ans=ans*MOD+a[i];
    	return M[ans];
    }
    inline int getans(vector<int>a)
    {
    	sort(a.begin()+1,a.end(),cmp);
    	int ans=0;
    	for(int i=0,sz=a.size();i<sz;i++)ans=ans*MOD+a[i];
    	return M[ans];
    }
    inline void init()
    {
    	for(int i=2;i<=100;i++)
    	{
    		if(!f[i])pri[++tot]=f[i]=i;
    		for(int j=1;j<=tot&&pri[j]<=f[i];j++)
    		{
    			int tmp=pri[j]*i;
    			if(tmp>100)break;
    			f[tmp]=pri[j];
    		}
    	}
    }
    
    inline void work(BIGNUM now,int pos,int x)
    {
    	p[++cnt]=make_pair(now,d);
    	for(int i=1;i<=x&&now*pri[pos]<=N;i++)
    		now=now*pri[pos],d[pos]=i,work(now,pos+1,i),d[pos]=0;
    }
    
    int main()
    {
    	init(),N.getnum(1);
    	for(int i=1;i<=24;i++)N=N*10;
    	d.resize(K);
    	BIGNUM num;num.getnum(1);
    	work(num,1,100);
    	sort(p+1,p+cnt+1);
    	for(int i=1;i<=cnt;i++)
    	{
    		long long val=0;
    		for(int j=0,sz=p[i].second.size();j<sz;j++)val=val*MOD+p[i].second[j];
    		M[val]=i;
    	}
    	ans[1]=0;
    	for(int i=0;i<=K;i++)sum[1][i]=0;
    	for(int i=2;i<=cnt;i++)
    	{
    		for(int j=K-1;j>=0;j--)
    		{
    			sum[i][j]=sum[i][j+1];
    			if(p[i].second[j])
    			{
    				vector<int>tmp=p[i].second;tmp[j]--;
    				sum[i][j]=upd(sum[i][j]+sum[solve(tmp,j)][j]);
    			}
    		}
    		int tmp=1;
    		for(int j=0,sz=p[i].second.size();j<sz;j++)tmp=1ll*tmp*(p[i].second[j]+1)%MOD;
    		ans[i]=1ll*(sum[i][0]+tmp)*ksm(tmp-1,MOD-2)%MOD;
    		for(int j=0;j<=K;j++)sum[i][j]=upd(sum[i][j]+ans[i]);
    	}
    	BIGNUM n;
    	while(~scanf("%s",s))
    	{
    		int tmp=strlen(s);
    		for(int i=tmp-1;~i;i--)s[25-tmp+i]=s[i];
    		for(int i=0;i<25-tmp;i++)s[i]='0';
    		long long pw=D/10;
    		n.getnum(0);
    		for(int i=13;i<25;i++)n.p[1]+=1ll*pw*(s[i]-48),pw/=10;
    		pw=D;
    		for(int i=0;i<13;i++)n.p[0]+=1ll*pw*(s[i]-48),pw/=10;
    		int m=getint();
    		vector<int>a;
    		a.resize(1);
    		for(int i=1;i<=m;i++)
    		{
    			int x=getint(),cnt=0;
    			while(n%x==0)cnt++,n=n/x;
    			a.push_back(cnt);
    		}
    		a.resize(K);
    		printf("%d
    ",ans[getans(a)]);
    	}
    }
    

  • 相关阅读:
    分层开发的优势
    分层开发的特点
    三层开发遵循的原则
    为什么需要分层
    什么是JNDI
    为什么需要JavaBean
    连接池中的连接对象是由谁创建的呢?
    什么是连接池技术
    为什么使用连接池?(为什么要使用JNDI)
    Servlet加载
  • 原文地址:https://www.cnblogs.com/Darknesses/p/13068615.html
Copyright © 2011-2022 走看看