OJの問題に遭遇ブラシ6(190406-)

1.poj 3071(ダイナミックプログラミングの問題)

長い戦争は、このタイトルは実際には午後のために行います。

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<math.h>
using namespace std;
#define M 128

int n, team_num, comp_round,num,weight,signal,res_i;
double mat[M][M],win[M][8],temp_win;

int main()
{
	for (int i = 0; i < M; ++i)
		win[i][0] = 1;
	while (scanf_s("%d", &n) && n >= 0)
	{
		num = 1<<n;
		res_i = 0;

		//get matrix
		for (int i = 0; i < num; ++i)
		{
			for (int j = 0; j < num; ++j)
			{
				scanf_s("%lf" ,mat[i]+j);
			}
			getchar();
		}
		
		weight = 1;
		for (int j = 1; j <= n; ++j)
		{
			for (int i = 0; i < num; ++i)
			{
				signal = (i/weight*weight) ^ (2*weight - 1);
				temp_win = 0;
                //这里有一种巧妙的方法:判断q和i的二进制前(j-1)位是否相同,这里用异或的方法就行
				for (int q = signal; q > signal - weight; --q)
				{
					temp_win += win[q][j-1] * mat[i][q];
				}
				win[i][j] = temp_win*win[i][j-1];
			}
			weight *= 2;//pow(2,j)
		}

		for (int i = 0; i < num; ++i)
		{
			if (win[res_i][n] < win[i][n])
			{
				res_i = i;
			}
		}
		printf("%d\n",res_i+1);
	}
	return 0;
}

2。

#include"stdafx.h"
#include <iostream>
#include<cstdio>
#include<string>
#include<vector>
#include<algorithm>
#include<math.h>
#include<map>
using namespace std;

int T, N,pai[13],res;
string card;
map<string, int> val;

int main()
{
	val.insert(pair<string, int>("A", 1));
	val.insert(pair<string, int>("2", 2));
	val.insert(pair<string, int>("3", 3));
	val.insert(pair<string, int>("4", 4));
	val.insert(pair<string, int>("5", 5));
	val.insert(pair<string, int>("6", 6));
	val.insert(pair<string, int>("7", 7));
	val.insert(pair<string, int>("8", 8));
	val.insert(pair<string, int>("9", 9));
	val.insert(pair<string, int>("10", 10));
	val.insert(pair<string, int>("J", 11));
	val.insert(pair<string, int>("Q", 12));
	val.insert(pair<string, int>("K", 13));

	cin >> T;
	for (int i = 0; i < T; ++i)
	{
		cin >> N;
		memset(pai, 0, sizeof(pai));
		res = 0;
		for (int j = 0; j < N; ++j)
		{
			cin >> card;
			pai[val[card]]++;
		}

		//find consistent array
		int c_len = 0;
		for (int k = 0; k < 13; ++k)
		{
			if (k < 13 && pai[k])
				c_len++;
			else
			{
				if (c_len > 4)
				{
					for (int len_i = 5; len_i <= c_len; ++len_i)
					{
						int temp_multi = 1;
						//the last one
						for (int len_j = 0; len_j < len_i; ++len_j)
						{
							temp_multi *= pai[k-1-len_j];
						}
						res += temp_multi;
						//then other former ones
						for (int len_l = 1; len_l + len_i <= c_len; ++len_l)
						{
							res += temp_multi / pai[k - len_l] * pai[k - len_i - 1];
						}
					}
				}
				c_len = 0;
			}
		}
		cout << res << endl;
	}

	return 0;
}

3.poj 3252ダイナミックプログラミング

#include"stdafx.h"
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;

int input[2], res[2], c[34][34],bin_N[35],
factorial[16] = { 2, 6, 20, 70, 252, 924, 3432, 12870, 48620,184756 ,705432 ,2704156,10400600,40116600, 155117520, 601080390 },
N_LEN_VAL[32] = { 0, 1, 2, 6, 11, 27, 49, 113, 206, 462, 848, 1872, 3458, 7554, 14030, 30414, 56747, 122283, 229045, 491189, 923099, 1971675, 3716111, 7910415, 14946945, 31724161, 60078293, 127187157, 241346585, 509782041, 969094193, 2042836017 };

//1st step: to calculate how many numbers exist in the length of n
long long N_LenNum(int n)
{
	if (n <= 1)
		return 0;
	else if (n == 2)
		return 1;
	return (1 << (n - 2)) - (n%2?(factorial[n/2-1]/2):0);
}

//2nd step: to transform n from dec to bin
void trans_D2B(int n)
{
	int digit = 0;
	while (n)
	{
		bin_N[++digit] = n % 2;
		n >>= 1;
	}
	bin_N[0] = digit;
}

//3rd step: to calculate combination
void cal_combi()
{
	c[0][0] = 0;
	for (int i = 1; i <= 33; ++i)
	{
		c[i][0] = c[i][i] = 1;
	}
	for (int i = 1; i <= 33; ++i)
	{
		for (int j = i + 1; j <= 33; ++j)
		{
			c[j][i] = c[j - 1][i - 1] + c[j - 1][i];
		}
	}
	c[0][0] = 1;//why???
}



int main()
{
	cal_combi();
	/*combinaiton calculation*/
	//factorial[0] = 2;
	//for (int i = 1; i < 16; ++i)
	//{
	//	factorial[i] = factorial[i-1]/(i+1);
	//	factorial[i] *= 2 * (i+1);
	//	factorial[i] /= 1 + i;
	//	factorial[i] *= 2 * i + 1;
	//}
	//for (int i = 0; i < 16; ++i)
	//	cout << factorial[i] << " ,";

	/*N_LEN_VALUE calculation*/
	//int dat[33];
	//memset(dat, 0, sizeof(dat));
	//for (int j = 1; j <= 32; ++j)
	//{
	//	dat[j] = dat[j - 1] + N_LenNum(j);
	//	cout << dat[j]<< ", ";
	//}

	scanf_s("%d%d",input,input+1);
	input[1]++;
	res[0] = res[1] = 0;
	for (int i = 0; i < 2; ++i)
	{
		int zero_digit = 0;
		trans_D2B(input[i]);
		if(bin_N[0] >= 2)
			res[i] += N_LEN_VAL[bin_N[0]-2];
		for (int j = bin_N[0] - 1; j >= 1; --j)
		{
			if (bin_N[j])
			{
				for (int k = (bin_N[0]+1)/2 - zero_digit-1; k <= j-1; ++k)//在余下的j个二进制位中,有k位要为0
					res[i] += c[j-1][k];
			}
			else
				zero_digit++;
		}
	}
	printf("%d\n",res[1]-res[0]);
	return 0;
}

(前の質問に似ている)4.poj 1850動的プログラミング

#include"stdafx.h"
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
#define N 26
char input[N+1],check[N+1];
int c[N+1][N+1];
int str_len = 0,signal = 1,res = 0;//signal == 1 means that the string is legal

void combi()
{
	c[0][0] = 1;
	for (int i = 1; i <= N; ++i)
		c[i][0] = c[i][i] = 1;
	for (int i = 1; i <= N; ++i)
		for (int j = i + 1; j <= N; ++j)
			c[j][i] = c[j - 1][i - 1] + c[j - 1][i];
}

int main()
{
	combi();
	check[0] = 'a' - 1;
	scanf_s("%s",input,N);
	//1st step:check its legality
	for (int i = 0; input[i]; ++i)
	{
		str_len++;
		check[i + 1] = input[i] + 1;
		if (input[i + 1])
		{
			if (input[i] >= input[i + 1])
			{
				signal = 0;
				break;
			}
		}
	}
	if (!signal)
	{
		printf("%d\n",0);
		return 0;
	}

	//2nd step: calculate the i-length string's number(i < str_len)
	for (int i = 1; i < str_len; ++i)
		res += c[26][i];
	//3rd step: calculate the str_len string's rank
	for (int i = 1; i <= str_len; ++i)
	{
		if (check[i-1] != input[i-1])
		{
			for (int j = 26 - input[i - 1] + 'a'; j <= 24 + 'a' - (i == 1 ? check[0] : input[i - 2]); ++j)
				res += c[j][str_len - i];
		}
	}
	printf("%d\n",res+1);
	return 0;
}

数式の結果

4.poj1942

RES = C(M + N、N)

キーはどのように計算することです。M、来、N、RES値は、符号なし32である対象は、式を解くまたは再発することにより、計算の定義RES乗算法により、考えられます。

#include<iostream>
#include<cstdio>

using namespace std;

unsigned long long M,N,res;

//直接用乘法计算结果(我记得有个结论说,C(m,n)总是整数,因此可以用下面的乘法来计算结果)
int main()
{
    while(scanf_s("%llu%llu",&M,&N) && (M || N))
    {
        res = 1;
        if(M > N)
        {
            unsigned long long temp = M;
            M = N;
            N = temp;
        }
        for(unsigned long long i = 0;i < M;++i)
        {
            res *=  M+N-i;
            res /= i+1;
        }
        printf("%llu\n",res);
    }
    return 0;
}

5.poj 1006中国の剰余定理

#include"stdafx.h"
#include<stdio.h>
#include<iostream>
#include<string.h>
#define M 21252
using namespace std;

int main()
{
	int p, e, i, d,res,case_n = 0;
	while (scanf_s("%d%d%d%d",&p,&e,&i,&d) && (p + e + i + d != -4))
	{
		case_n++;
		res = (5544 * p+14421*e+1288*i-d)%M;
		if (res)
			res = (res + M) % M;
		else
			res = M;
		printf("Case %d: the next triple peak occurs in %d days.\n",case_n,res);
	}
	return 0;
}

6.poj 2635

参考ブログ:https://www.cnblogs.com/kuangbin/archive/2012/04/01/2429463.html

使用する素数は、テーブルを再生し、何千あるいは思考の千分のに算術モジュロ

#include"stdafx.h"
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<vector>
#define M 1000
#define N 10000 //here we transfer from 1000-scale to 10000-scale
#define Nn 4
#define MM M*M
using namespace std;

bool primes[MM+1],signal;//(prime num is marked as 0)
int rec_prime[80*M],Kt[40];
char str[110];
int L, p,temp,prime_num = 0;

bool mod_N(int len, int p)
{
	long long  re = 0;//notice that here 10000^2 + any_num is very likely to exceed 2^32-1
	for (int i = len - 1; i >= 0; --i)
		re = (re * N + Kt[i]) % p;
	return !!re;
}

void output_prime()
{
	//set the array's initial value as 0
	memset(primes,0,sizeof(primes));
	for (int i = 4; i <= MM; i += 2)
		primes[i] = 1;

	for (int i = 3; i <= M; i += 2)
	{
		if (!primes[i])
		{
			temp = 2 * i;
			for (int j = i*i; j <= MM; j += temp)
			{
				primes[j] = 1;
			}
		}
	}

	for (int i = 2; i < MM; ++i)
		if (!primes[i])
			rec_prime[prime_num++] = i;
	rec_prime[prime_num++] = 1000003;
}

int main()
{
	//1st step: to create a table(All even composite numbers are not marked!!)
	output_prime();
	//2nd step: to check if K/table[i] is an integer, we use mod 
	while (scanf_s("%s%d", str, 110,&L), L)
	{
		int str_len = strlen(str);
		memset(Kt, 0, sizeof(Kt));
		signal = true;
		for (int i = 0; i < str_len; ++i)
		{
			int th_i = (str_len + Nn-1 - i) / Nn - 1;
			Kt[th_i] = Kt[th_i] * 10 + str[i] - '0';
		}
		str_len = (str_len + Nn-1) / Nn;
		for (int pi = 0; rec_prime[pi] < L; ++pi)
		{
			if (!mod_N(str_len, rec_prime[pi]))
			{
				signal = false;
				printf("BAD %d\n", rec_prime[pi]);
				break;
			}
		}
		if(signal)
			printf("GOOD\n");
	}
	return 0;
}

7.poj 3292

私は計算の方法と同様の方法素数ふるい法を使用して開始し、得られた結果は、自分のコンピュータ上で実行することはできません、私のアルゴリズムが大きすぎることを示し、この問題には適用されません。

それから私は、暴力のアイデアを比較ブログ、その状態を記録し、その後再びそれを通過する配列の直接の結果を開くに言及しました。なぜ、この方法は、もともとそれで死亡する素数のふるいを使用しましたか?I出力H-素数の数(1,000,000未満)、27%である27万、約。起因よう計算された量との間の有意な差異の数を、7%程度である1 / LN(x)は、約のみ百マイルが広く変化素数なので、乱暴な方法が、より速く。

#include"stdafx.h"
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;

#define N 1000001

int h, H[N],multi,H_Number[250001],
prime_count = 0;
void H_Num()
{
	memset(H, 0, sizeof(H));
	for (int i = 5; i <= N; i += 4)
	{
		for (int j = 5; j <= N; j += 4)
		{
			multi = i * j;
			if (multi > N)
				break;
			if (H[i] == 0 && H[j] == 0)
				H[multi] = 1;
			else
				H[multi] = -1;
		}
	}

	multi = 0;
	for (int i = 1; i <= 250000; i++)
	{
		if (H[(i<<2)+1] == 1)
		{
			multi++;
		}
		H_Number[i] = multi;
	}
}

int main()
{
	H_Num();
	while (scanf_s("%d",&h),h)
		printf("%d %d\n",h,H_Number[h/4]);
	return 0;
}

8.poj 2115

線形方程式の話題を解決するための古典的な金型。アルゴリズムリファレンス「の紹介アルゴリズムに」P555。参考ブログ:https://blog.csdn.net/lyy28906540​​6/article/details/6648546

話に少しありますが、1LL << Kと1 << kが異なっている(長い長いため種類は、)です!

#include"stdafx.h"
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;

long long A,B,C,k,a,b,n,d,ex,ey;

long long ExtendedEuclid(long long a, long long b,long long &x,long long &y)
{
	if (!b)
	{
		ex = 1;
		ey = 0;
		return a;
	}
	else
	{
		long long d = ExtendedEuclid(b,a%b,ex,ey);
		long long temp_ex = ex;
		ex = ey;
		ey = temp_ex - a / b * ey;
		return d;
	}
}

int main()
{
	while (scanf_s("%lld%lld%lld%lld", &A, &B, &C, &k), k)
	{
		a = C;
		b = B - A;
		n = 1 << k;
		d = ExtendedEuclid(a,n,ex,ey);
		if (b % d)
		{
			printf("FOREVER\n");
			continue;
		}
		else
		{
			ex = ex * b / d % n;
			ex = (ex%(n/d)+n/d) % (n/d);
			printf("%lld\n",ex);
		}
	}
	return 0;
}

9.poj 1002 

微妙に格納された文字列と(1):int型アレイストレージを使用した(参考ブログ:https://blog.csdn.net/thebestdavid/article/details/10986813)。

(2)のような出力の整数部、setw有する()または%04D、図4は、4ビット0がゼロよりも小さいことを示す表します。

#include"stdafx.h"
#include<stdio.h>
#include<string.h>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;

char input_str[100];
int phone_num[100010];

void print_phone(int num,int c)
{
	for (int i = 0; i < 7; ++i)
	{
		
	}
}

int main()
{
	int total_num,phone_len,phone_value,dup_num = 0,signal = 0;
	scanf_s("%d",&total_num);
	for (int gi = 0; gi < total_num; ++gi)
	{
		scanf_s("%s",input_str,100);
		phone_len = strlen(input_str);
		phone_value = 0;
		for (int si = 0; si < phone_len; ++si)
		{
			//transfer string to int
			if (input_str[si] == '-')
				continue;
			//get number
			else if (input_str[si] >= '0' && input_str[si] <= '9')
			{
				phone_value *= 10;
				phone_value += input_str[si] - '0';
			}
			else
			{
				phone_value *= 10;
				switch (input_str[si]) 
				{
					case 'A':
					case 'B':
					case 'C': phone_value += 2; break;
					case 'D': 
					case 'E': 
					case 'F': phone_value += 3; break;
					case 'G':
					case 'H':
					case 'I':phone_value += 4; break;
					case 'J':
					case 'K':
					case 'L':phone_value += 5; break;
					case 'M':
					case 'N':
					case 'O':phone_value += 6; break;
					case 'P':
					case 'R':
					case 'S':phone_value += 7; break;
					case 'T':
					case 'U':
					case 'V':phone_value += 8; break;
					case 'W':
					case 'X':
					case 'Y':phone_value += 9; break;
				}
			}
		}
		phone_num[gi] = phone_value;
	}

	sort(phone_num,phone_num+total_num);

	for (int pi = 0,counter = 0; pi < total_num; ++pi)
	{
		if (!pi || phone_num[pi - 1] == phone_num[pi])
		{
			counter++;
			if (pi + 1 == total_num)
			{
				printf("%03d-%04d %d\n", phone_num[pi] / 10000, phone_num[pi] % 10000, counter);
				signal = 1;
			}
		}
		else if(counter > 1)
		{
			printf("%03d-%04d %d\n", phone_num[pi-1]/10000, phone_num[pi - 1]%10000,counter);
			signal = 1;
			counter = 1;
		}

	}
	if (!signal)
		printf("No duplicates.\n");
	return 0;
}

10. POJ 2063コードのアイデアのフルバックパックは、参照することであるhttps://blog.csdn.net/hmc0411/article/details/78398872をこのブログ。

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int bond[11], v[11], dp[47002];
int add(int m, int n){
	m /= 1000;
	for(int i = 1; i <= n; ++i){
		for(int j = bond[i]; j <= m; ++j){
			dp[j] = max(dp[j], dp[j - bond[i]] + v[i]);
		}
	}
	return dp[m];
}
int main(){
	int T;
	scanf("%d", &T);
	while(T--){
		int n, m, d;
		scanf("%d %d %d", &m, &d, &n);
		for(int i = 1; i <= n; ++i){
			scanf("%d %d", &bond[i], &v[i]);
			bond[i] /= 1000;
		}
		memset(dp, 0, sizeof(dp));
		for(int i = 1; i <= d; ++i){
			m += add(m, n);
		}
		printf("%d\n", m);
	}
}
 
/*
题意:一家银行,10种不同的投资方案,每种有一个投资金额和每年的回报额,最多40年,每年得到的
回报额可以参加下一年投资。问n年后最多可以得到多少钱?
思路:
对于每一年来说,用完全背包求最大收益是很容易的。那么对于n年,我们只需要把每年的收益加上去再求
新的一次背包就好了。最多40年,每年收益比最大0.1,求一下背包的上限。然后暴力跑背包就好了。
*/

11.poj 1252フルバックパック(2回)参考:https://www.cnblogs.com/xinsheng/p/3457126.html

#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string>
#include<iostream>
#include<map>
#include<vector>
using namespace std;
int dp[2010],cash[6];

int main()
{
	int N,maxRes;
	double averRes;
	scanf_s("%d",&N);
	while(N--)
	{
		averRes = maxRes = 0;
		//get input
		for (int j = 0; j < 6; ++j)
			scanf_s("%d", &cash[j]);

		memset(dp,2100,sizeof(dp));
		dp[0] = 0;

		//dp for addition
		for (int i = 0; i < 6; ++i)
		{
			for (int j = cash[i]; j <= 2000; ++j)
			{
				dp[j] = min(dp[j],dp[j-cash[i]]+1);
			}
		}

		//dp for subtraction
		for (int i = 0; i < 6; ++i)
		{
			for (int j = 2000 - cash[i]; j >= 1; --j)
			{
				dp[j] = min(dp[j],dp[j+cash[i]]+1);
			}
		}

		for (int i = 1; i <= 100; ++i)
		{
			averRes += dp[i];
			maxRes = max(maxRes, dp[i]);
		}
		printf("%0.2f %d\n",averRes/100.0,maxRes);
	}
}

12. POJ 1948リファレンスナップザック問題https://blog.csdn.net/xiefubao/article/details/23224659

#include"stdafx.h"
#include <iostream>
#include <vector>
#include <string>
#include<cstdio>
#include<math.h>
#include<algorithm>
using namespace std;

#define LEN 40
#define P 800

bool OK(int i, int j, int k)
{
	return ((i + j) > k) && ((i + k) > j) && ((j+k)>i);
}

double getarea(int i, int j, int k)
{
	double p = (i + j + k) / 2.0;
	return sqrt(p*(p-i)*(p-j)*(p-k));
}

int main()
{
	int N, periM = 0,sides[LEN+1];
	double res = 0;
	bool dp[P + 1][P + 1];
	//get input
	scanf_s("%d",&N);
	for (int i = 0; i < N; ++i)
	{
		scanf_s("%d", &sides[i]);
		periM += sides[i];
	}

	//check whether triangle exists
	dp[0][0] = 1;
	for (int i = 0; i < N; ++i)
	{
		for (int k = periM/2; k >= 0; --k)
		{
			for (int j = k; j >= 0; --j)
			{
				if (k - sides[i] >= 0 && dp[k - sides[i]][j])//保证k是边长集合中部分元素之和
					dp[k][j] = 1;
				if (j - sides[i] >= 0 && dp[k][j - sides[i]])//dp[k][j]可以从dp[k-sides[i]][j]获取,也可以从dp[k][j-sides[i]]获取
					dp[k][j] = 1;
			}
		}
	}

	for (int i = 0; i <= periM/2; ++i)
	{
		for (int j = 0; j <= i; ++j)
		{
			if (dp[i][j] && OK(i, j, periM - i - j))
				res = max(res, getarea(i, j, periM - i - j));
		}
	}
	if (res == 0)
		printf("-1\n");
	else
		printf("%d\n",(int)(res*1000)/10);
	return 0;
}

13. POJ 1976 01ナップザック問題

#include"stdafx.h"
#include <iostream>
#include <vector>
#include <string>
#include<stdlib.h>
#include<cstdio>
#include<math.h>
#include<algorithm>

#define NUM 50001
using namespace std;

int capa[NUM], sumC[NUM],dp[4][NUM];

int main()
{
	int rounds, lenTrain,pullNum;
	scanf_s("%d",&rounds);
	while (rounds--)
	{
		//get input
		scanf_s("%d",&lenTrain);
		capa[0] = 0;
		for (int i = 1; i <= lenTrain; ++i)
			scanf_s("%d",&capa[i]);
		scanf_s("%d",&pullNum);

		sumC[0] = capa[0];
		for (int i = 1; i <= pullNum; ++i)
			sumC[i] = sumC[i-1] + capa[i];
		for (int i = pullNum+1; i <= lenTrain; ++i)
			sumC[i] = sumC[i-1] + capa[i] - capa[i - pullNum];

		//dp recursion
		memset(dp,0,sizeof(dp));
		for (int i = 1; i <= 3; ++i)
			for (int j = pullNum; j <= lenTrain; ++j)
				dp[i][j] = max(dp[i][j-1],dp[i-1][j-pullNum]+sumC[j]);
		
		printf("%d\n",dp[3][lenTrain]);
	}
}

14. POJ 3904メビウス反転基準https://blog.csdn.net/qq_42671946/article/details/89161719

#include"stdafx.h"
#include <iostream>
#include <vector>
#include <string.h>
#include<stdlib.h>
#include<cstdio>
#include<string.h>
#include<math.h>
#include<algorithm>

#define N 10001
using namespace std;

int mobius[N],input[N],F[N];
bool sig[N];

//计算莫比乌斯函数
void mobiusFunc()
{
	int i, j;
	for (i = 1; i < N; ++i)
	{
		mobius[i] = 1;
		sig[i] = false;
	}
	for (i = 2; i < N; ++i)
	{
		if (sig[i])//如果已经处理过,则跳过
			continue;
		for (j = i; j < N; j += i)
		{
			sig[j] = true;
			if ((j / i) % i == 0)
			{
				mobius[j] = 0;//如果因数包含某素数的多次方,则置零
				continue;
			}
			mobius[j] = -mobius[j];//遍历到数字j,表示素数i是j的因数,所以要变号
		}
	}
}

//计算组合数C(4,m)
long long combinCalclu(long long num)
{
	return num * (num - 1)*(num - 2)*(num - 3) / 24;
}

int main()
{
	mobiusFunc();
	int n;

	//get input
	while (scanf_s("%d",&n) == 1)
	{
		int maxNum = 0;
		for (int i = 0; i < n; ++i)
		{
			scanf_s("%d", &input[i]);
			maxNum = max(maxNum,input[i]);
		}

		//计算gcd为1的倍数的四元组个数
		memset(F,0,sizeof(F));
		for (int i = 0; i < n; ++i)
		{
			for (int j = 1; j*j <= input[i]; ++j)
			{
				if (input[i] % j == 0)
				{
					F[j]++;
					if (j*j != input[i])
						F[input[i] / j]++;
				}
			}
		}

		//根据莫比乌斯反演公式求得
		long long res = 0;
		for (int i = 1; i <= maxNum; ++i)
		{
			if (F[i] >= 4)
				res += mobius[i] * combinCalclu(F[i]);
		}
		printf("%lld\n",res);
	}
}

 

公開された22元の記事 ウォンの賞賛0 ビュー7398

おすすめ

転載: blog.csdn.net/georgeandgeorge/article/details/89059472