1. 程式人生 > >牛客小白月賽9: div.2 A(線性篩)

牛客小白月賽9: div.2 A(線性篩)

連結:https://ac.nowcoder.com/acm/contest/275/J
來源:牛客網
 

題目描述

定義 f(n,k) 表示將 n 拆分成 k 個有序正整數乘積的方案數。
給定 n,k,,求f(1,k)~f(n,k)
舉個例子,假設要求 f(4,3) ,因為



所以 f(4,3)=6 。

輸入描述:

第一行兩個正整數 n,k 。

輸出描述:

設,且gi ≥ 0,且gi儘可能的小

設

你只需要輸出T就行了

輸入

4 3

輸出

11

說明

f1,3=1,f2,3=3,f3,3=3,f4,3=6

 

有點懶,直接放下官網題解吧

那麼一個線性篩就搞定了

 

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
#define mod 1000000007
LL F[10000005], inv[686] = {0,1};
int cnt, flag[10000005], num[10000005], pri[1000005];
int main(void)
{
	LL ans, n, i, j, k;
	scanf("%lld%lld", &n, &k);
	k %= mod;
	for(i=2;i<=666;i++)
		inv[i] = (mod-mod/i)*inv[mod%i]%mod;
	for(i=2;i<=10000000;i++)
	{
		if(flag[i]==0)
		{
			num[i] = 1;
			pri[++cnt] = i;
			F[i] = k;
		}
		for(j=1;j<=cnt&&i*pri[j]<=10000000;j++)
		{
			flag[i*pri[j]] = 1;
			if(i%pri[j]==0)
			{
				num[i*pri[j]] = num[i]+1;
				F[i*pri[j]] = F[i]*(num[i]+k)%mod*inv[num[i]+1]%mod;
				break;
			}
			else
			{
				num[i*pri[j]] = 1;
				F[i*pri[j]] = F[i]*k%mod;
			}
		}
	}
	ans = 0;
	F[1] = 1;
	for(i=1;i<=n;i++)
		ans ^= (F[i]+i)%mod;
	printf("%lld\n", ans);
	return 0;
}
/*
10000000 1000000000000000000
*/