• [CSP-S模拟测试]:Six(数学)


    题目传送门(内部题85)


    输入格式

    一个正整数$N$。


    输出格式

    一个数表示答案对$1000000007$取模后的结果


    样例

    样例输入1:

    6

    样例输出1:

    28

    样例输入2:

    203021

    样例输出2:

    33628

    样例输入3:

    60357056536

    样例输出3:

    907882

    样例输入4:

    12156144

    样例输出4:

    104757552


    数据范围与提示

    样例解释:

    第一组样例:${(2),(2,2),(2,2,3),(2,2,3,3),(2,3),(2,3,2),(2,3,2,3),(2,3,3),(2,3,3,2),(2,6),(2,6,3),(3),(3,2),(3,2,2),(3,2,2,3),(3,2,3),(3,2,3,2),(3,3),(3,3,2),(3,3,2,2),(3,6),(3,6,2),(6),(6,2),(6,2,3),(6,3),(6,3,2),(6,6)}$

    数据范围:

    对于$32\%$的数据,$N$最多有$2$个不同的质因数
    对于$56\%$的数据,$N$最多有$4$个不同的质因数
    对于$100\%$的数据,$Nleqslant 10^{15}$且$N$最多有$6$个不同的质因数


    题解

    爆搜能有一半的分,在加上记忆化就$A$了……

    记录一下二进制位下每一位$1$的个数状态,但是注意$1$可以是两个,所以还需要再开一个数记录一下是否已经达到了两个。

    队列里的数最多只有$12$个,所以状态数也不多,$50,000$以内,用$map$记录就好了。

    时间复杂度:$Theta(sqrt{N}+50,000)$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    const int mod=1000000007;
    map<pair<long long,long long>,int>dp;
    long long N;
    long long d[1001],fla[1001],top;
    pair<long long,int> pri[10];
    long long dfs(int x,long long res1,long long res2)
    {
    	if(dp[make_pair(res1,res2)])return dp[make_pair(res1,res2)];
    	dp[make_pair(res1,res2)]=1;
    	for(int i=1;i<(1<<top);i++)
    	{
    		int sum=0;bool flag=0;
    		for(int j=1;j<(1<<top);j++)
    		{
    			if(!(i&j))continue;
    			if((res1>>j)&1)sum++;
    			if((res2>>j)&1)flag=1;
    			if(flag||sum>1)goto nxt;
    		}
    		if((res1>>i)&1)dp[make_pair(res1,res2)]=(dp[make_pair(res1,res2)]+d[i]*dfs(x+1,res1^(1LL<<i),res2|(1LL<<i))%mod)%mod;
    		else dp[make_pair(res1,res2)]=(dp[make_pair(res1,res2)]+d[i]*dfs(x+1,res1|(1LL<<i),res2)%mod)%mod;
    		nxt:;
    	}
    	return dp[make_pair(res1,res2)];
    }
    int main()
    {
    	scanf("%lld",&N);
    	for(long long i=2;i*i<=N;i++)
    		if(!(N%i))
    		{
    			pri[++top].first=i;
    			while(!(N%i))
    			{
    				pri[top].second++;
    				N/=i;
    			}
    		}
    	if(N!=1)pri[++top]=make_pair(N,1);
    	d[0]=1;
    	for(int i=1;i<=top;i++)fla[1<<i-1]=i;
    	for(int i=1;i<(1<<top);i++)d[i]=d[i^(i&-i)]*pri[fla[i&-i]].second;
    	printf("%lld
    ",dfs(0,0,0)-1);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    vertical-align:middle 垂直居中无效的原因
    meta标签的使用
    异常重试框架Spring Retry实践
    springboot 整合retry(重试机制)
    Centos7-Docker1.12开启守护进程(远程调用)
    Centos7安装docker与docker-compose
    Centos 下 Jenkins2.6 + Git + Maven Shell一件部署与备份
    Docker实战
    利用 Nginx 实现限流
    Feign拦截器应用 (F版)
  • 原文地址:https://www.cnblogs.com/wzc521/p/11736874.html
Copyright © 2020-2023  润新知