zoukankan      html  css  js  c++  java
  • HDU 5514

    题意: 给你 N 个数 和 一个 M;

        对于 每一个 Ni , 乘以 K 取摸 M 都有一个 集合, 把所有集合合并, 求和

               Σ ai ( ai → K * Ni % M )

    思路 :   最开始 直接求一边gcd , 然后容斥。。。。 结果状态有 2 ^  (1e4)....

          反着求 M 的约数, 然后记录要用到的约数, 对于这些进行容斥就好了(不能状压)

          

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxn = 1e5 + 131;
    LL gcd(LL a, LL b){
    	return b == 0 ? a : gcd(b, a % b);
    }
    
    LL P[maxn], cnt;
    void GetP(LL m){
    	cnt = 0;
    	for(LL i = 1; i <= sqrt(m); ++i)
    	{
    		if(m % i == 0)
    		{
    			P[cnt++] = i;
    			if(i * i != m) P[cnt++] = m / i;
    		}
    	}
    	sort(P,P+cnt);
    }
    
    LL Vis[maxn], Num[maxn];
    
    int main()
    {
    	int T;
    	scanf("%d", &T);
    	for(int kase = 1; kase <= T; ++kase)
    	{
    		LL n, m;
    		scanf("%lld %lld", &n, &m);
    		GetP(m);
    		LL u;
    		memset(Vis,0, sizeof(Vis));
    		memset(Num,0, sizeof(Num));
    		for(int i = 0; i < n; ++i)
    		{
    			scanf("%lld", &u);
    			LL tmp = gcd(u, m);
    			for(LL j = 0; j < cnt; ++j)
    			{
    				if(P[j] % tmp == 0)
    				Vis[j] = 1;
    			}
    		}
    		//cout << P[cnt - 1 ] << endl;
    		Vis[cnt -1] = 0;
    		LL Ans = 0;
    		for(LL i = 0; i < cnt; ++i) // 容斥 
    		{
    			if(Vis[i] != Num[i])
    			{
    				LL tmp = m / P[i], D = Vis[i] - Num[i];
    				Ans += (tmp + 1) * tmp / 2 * P[i] * D;
    				for(LL j = i; j < cnt; ++j)
    				{
    					if(P[j] % P[i] == 0)
    					Num[j] += D;
    				} 
    			}
    		}
    		
    		printf("Case #%d: %lld
    ", kase, Ans);
    	}
    }
    
  • 相关阅读:
    快速排序
    归并排序
    堆排序
    通过先序和中序创建二叉树
    插入排序
    二叉排序树
    九宫重排
    字符串匹配 sunday算法
    傻逼数学题(math)
    最近点对学习笔记
  • 原文地址:https://www.cnblogs.com/aoxuets/p/5506857.html
Copyright © 2011-2022 走看看