zoukankan      html  css  js  c++  java
  • luogu2429 制杖题

    题目大意

    求不大于 m 的、 质因数集与给定有n个元素的质数集有交集的自然数之和。

    数据范围

    1 2 3 n*m<=10^7
    4 5 n<=2,m<=10^9
    6 7 n<=20,m<=10^8
    8 9 10 n<=20,m<=10^9

    前三个点

    n可能会很大。暴力枚举从1到m的每一个数看看是否满足条件即可。

    后七个点

    m内因数中包含质数p的数分别为p*1,p*2,p*3...p*m/i。用等差数列的知识可以得到该数列的和,记为f(i)。根据容斥原理,结果为sum(f(p[i]))-sum(f(p[i]*p[j]))+sum(f(p[i]*p[j]*p[k]))-...。

    n个元素的集合的子集数量为2^n,而后七个点n<=20,符合要求。

    注意事项

    • 每次想要对P取模时,不能直接x%P,而应当为(x%P+P)%P,因为运算中变量有可能暂时是负的。
    • 作为判断终止条件的当前乘积prod不能取模。
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cassert>
    using namespace std;
    
    #define ll long long
    const int P = 376544743, INV2 = 188272372;
    const int MAX_N = 100000;
    ll Primes[MAX_N];
    ll N, M, Ans;
    
    ll Mod(ll x, ll p)
    {
    	return (x % p + p) % p;
    }
    
    ll Mult(ll a, ll b)
    {
    	ll ans = 0;
    	while (b)
    	{
    		if (b & 1)
    			ans = Mod(ans + a, P);
    		a = Mod(a + a, P);
    		b >>= 1;
    	}
    	return ans;
    }
    
    void Dfs(int cnt, int p, ll prod)
    {
    	assert(prod <= M);
    	if (cnt > 0)
    	{
    		ll n = M / prod;
    		ll delta = Mult(Mult(n, n + 1), INV2);
    		delta = Mult(delta, prod);
    		if (cnt & 1)
    			Ans = Mod(Ans + delta, P);
    		else
    			Ans = Mod(Ans - delta, P);
    	}
    	if (p == N)
    		return;
    	ll NextProd;
    	for (int i = p + 1; i <= N && (NextProd=prod*Primes[i])<=M; i++)
    		Dfs(cnt + 1, i, NextProd);
    }
    
    ll way1()
    {
    	ll ans = 0;
    	for (ll i = 1; i <= M; i++)
    	{
    		for (ll j = 1; j <= N && Primes[j] <= i; j++)
    		{
    			if (i % Primes[j] == 0)
    			{
    				ans = (ans + i) % 376544743;
    				break;
    			}
    		}
    	}
    	return ans;
    }
    
    int main()
    {
    	scanf("%lld%lld", &N, &M);
    	for (int i = 1; i <= N; i++)
    		scanf("%lld", Primes + i);
    	sort(Primes + 1, Primes + N + 1);
    	if (N*M <= 10000000)
    		printf("%lld
    ", way1());
    	else
    	{
    		Ans = 0;
    		Dfs(0, 0, 1);
    		printf("%lld
    ", Ans);
    		//printf("%lld
    ", Ans%P);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    JDK5.0新特性系列目录
    JDK5.0新特性系列11.5.2线程 同步装置之CountDownLatch
    JDK5.0新特性系列11.5.4线程 同步装置之Exchanger
    JDK5.0新特性系列11.5.1线程 同步装置之Semaphore
    Axure RP Pro 6.0 原型设计工具(产品经理必备)
    JDK5.0新特性系列11.4线程 Condition
    OLTP 和 OLAP 的区别
    JDK5.0新特性系列11.5.3线程 同步装置之CyclicBarrier
    电脑通过手机上网的设置
    (转)刚开始Outlook Addin的布署问题
  • 原文地址:https://www.cnblogs.com/headboy2002/p/8935006.html
Copyright © 2011-2022 走看看