HDU6265(能被n整除的因子與其歐拉乘積的和)

由這兩個公式聯立

公式很顯然我們可以消去d可以推出:

我們知道對於每個pi,我們都有qi種取法,根據歐拉函數的性質我們知道每一個質數的的倍數的歐拉函數值 都等於這個質數的歐拉函數值等於其擴大的倍數,正好其外面縮小倍數也爲其歐拉擴大的倍數,所以這組數對答案的貢獻是相同的。

我們可以通過類比的方法得到所有的答案:我們可以通過已經給的質因子知道他一共有多少因子,通過歐拉函數的性質我們可以將對答案貢獻相同的一起計算。

由例2爲例:

質因子爲 2 、3   指數都爲2。

我們可以通過枚舉取不取質因子來分析:   全不取:上式答案爲 n本身,等於phi(1)*n。

取 第一個質因子2 ,      取一個   計算的是  phi[2]*(n/2);取兩個   計算的就是 phi[4]*(n/4) 。你可以發現這兩個結果是相同的,因爲上面說的歐拉函數的性質。所以我們算只取一個質因子的時候要乘以qi,選擇的數量。

取 第二個質因子3 ,     取一個    計算的就是  phi[3]*(n/3),取兩個 計算的就是  phi[9]*(n/9)。你也知道這樣個結果是相同的,所以我們可以一起計算。

取 兩個質因子2和,      取一個 2和一個3    計算的就是   phi[6]*(n/6),取兩個2和一個3   就是計算的    phi[12]*(n/12),取1個2和兩個3就是計算的  phi[18]*(n/18),取兩個2和兩個3,就是計算的  phi[36]*(n/36);這幾類的答案也是相同的,我們可以一起計算。

這樣就將所有的因子枚舉完全。即答案。

但是                  這道題時間複雜度卡常!!!!

圖省事我用了以前容斥裝壓部分的板子,改了改沒想到T了!

T的部分代碼如下:

   for(int i=0;i<(1<<m);i++)
	    {
	    	ll res=x;
	    	for(int j=0;j<m;j++)
	    	{
	    	  if(i&(1<<j))
	    	   res=res*(p[j]-1)%mod*q[j]%mod*inv[j]%mod;
	        }
	    	ans=(ans+res)%mod;
	    }

不T的代碼如下:

void dfs(ll pos,ll x){
	if(pos==m)
	{
		ans=(ans+x)%mod;
		return;
	}
	dfs(pos+1,x);
	dfs(pos+1,x*(p[pos]-1)%mod*q[pos]%mod*inv[pos]%mod);
}

僅僅比dfs多跑了一邊每個因子判斷它取不取,只不多了一個常數20。真的慘!

代碼如下:

#include<bits/stdc++.h>
typedef long long ll;
const int maxn = 25;
const int mod = 998244353;
using namespace std;
int p[maxn],q[maxn],inv[maxn],m;
ll ans;
ll pow_mod(ll a,ll b){
	ll res=1;
	while(b)
	{
		if(b&1) res=res*a%mod;
		b=b>>1;
		a=a*a%mod;
	}
	return res;
}
void init(int m){
	for(int i=0;i<m;i++)
	inv[i]=pow_mod(p[i],mod-2);
}
void dfs(ll pos,ll x){
	if(pos==m)
	{
		ans=(ans+x)%mod;
		return;
	}
	dfs(pos+1,x);
	dfs(pos+1,x*(p[pos]-1)%mod*q[pos]%mod*inv[pos]%mod);
}
int main()
{
	int t;
	ll x;
	scanf("%d",&t);
	while(t--)
	{
		ans=0;
		x=1;
		scanf("%d",&m);
		for(int i=0;i<m;i++)
		{
		 scanf("%d %d",&p[i],&q[i]);
		 x=x*pow_mod(p[i],q[i])%mod;
	    }
	    init(m);
	    dfs(0,x);
	    printf("%lld\n",ans);
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章