列表

详情


NC17403. Calculating sums

描述

Niuniu likes calculating sums. He has recently learnt how to calculate sums using various methods. Here is one of them:

Note that [x] is 1 when x is true and 0 when x is false.
Can you calculate the sum? The answer may be large, so please calculate the sum modulo a given number K.

输入描述

The only line contains three integers N, M, K.
1 ≤ N ≤ 109, 1 ≤ M ≤ 106, 1 ≤ K ≤ 109

输出描述

Print a single line with one number, which is the answer.

示例1

输入:

2 3 3

输出:

0

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 1436ms, 内存消耗: 4452K, 提交时间: 2019-02-28 09:43:26

/*
题意定简单的, 就是需要扩展crt合并一下

*/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<cmath>
#define ll long long
#define LL long long
#define M 1000100
#define mmp make_pair
using namespace std;
int read() {
	int nm = 0, f = 1;
	char c = getchar();
	for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
	for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
	return nm * f;
}

int poww(int a, int b, int mod) {
	int ans = 1, tmp = a;
	for(; b; b >>= 1, tmp = 1ll * tmp * tmp % mod) if(b & 1) ans = 1ll * ans * tmp %mod;
	return ans;
}
int p[44], cnt[44], pq[44], f[M], tot, n, m, k, ans;

int main() {
	n = read() & (~1), m = read(), k = read();
	int now = k;
	for(int i = 2; i * i  <=  now; i++) {
		if(now % i == 0) {
			p[tot] = i, pq[tot] = 1;
			cnt[tot] = 0;
			while(now % i == 0) cnt[tot]++, pq[tot] *= i, now /= i;
			tot++;
		}
	}
	if(now > 1) p[tot] = pq[tot] = now, cnt[tot] = 1, tot++;
	for (int nzz=0; nzz<tot; nzz++) {
		int mod = pq[nzz], phi = mod/p[nzz]*(p[nzz]-1);
		int pre=1,ct=0;
		for (int i=0,sz=min(m+cnt[nzz],n+1); i<=sz; i++) {
			int tmp1=n+2-i,cnt1=0,tmp2=i+1,cnt2=0;
			while (tmp1%p[nzz]==0) tmp1/=p[nzz], cnt1++;
			while (tmp2%p[nzz]==0) tmp2/=p[nzz], cnt2++;
			pre = pre*(LL)tmp1%mod*poww(tmp2,phi-1,mod)%mod;
			ct = ct+cnt1-cnt2;
			if (ct >= cnt[nzz]) f[i]=0;
			else f[i] = pre*(LL)poww(p[nzz],ct,mod)%mod;
		}
		int ret=0;
		if (p[nzz]==2) {
			for (int i=0; i<=m; i+=2) {
				int d=0;
				for (int j=i+1,tmp=1; tmp; j++) {
					d=(d+tmp*(LL)f[j])%mod;
					tmp=tmp*(LL)(mod-2)%mod;
				}
				ret = (ret+d)%mod;
			}
		} else {
			LL inv2 = poww(2,phi-1,mod);
			int d = f[0]*inv2%mod;
			ret = (ret+d)%mod;
			for (int i=1; i<=m; i++) {
				d = (f[i]-d+mod)*inv2%mod;
				if (i%2==0) ret = (ret+d)%mod;
			}
		}
		ans = (ans + ret*(LL)(k/mod)%k*poww(k/mod,phi-1,mod))%k;
	}
	cout << ans << "\n";
	return 0;
}


C++11(clang++ 3.9) 解法, 执行用时: 1454ms, 内存消耗: 43484K, 提交时间: 2018-08-12 18:39:14

//by yjz
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll qpow(ll x,ll k,ll md){return k==0?1:1ll*qpow(1ll*x*x%md,k>>1,md)*(k&1?x:1)%md;}
int N,M,K,X,cnt[33],a[1001111],b[1001111];
int phi;
const int B=1001111;
int pr[15],pk[15],pn,tab[15][B];
void fac(int K)
{
	int OK=K;
	phi=K;
	for(int i=2;i*i<=K;i++)
	{
		if(K%i==0)
		{
			phi=phi/i*(i-1);
			while(K%i==0)K/=i,pk[pn]++;
			pr[pn++]=i;
		}
	}
	if(K>1)
	{
		phi=phi/K*(K-1);
		pk[pn]=1;
		pr[pn++]=K;
	}
	for(int i=0;i<pn;i++)
	{
		tab[i][0]=1;
		for(int j=1;j<B;j++)tab[i][j]=1ll*tab[i][j-1]*pr[i]%OK;
	}
}
void mul(int x)
{
	for(int i=0;i<pn;i++)
	{
		while(x%pr[i]==0)
		{
			x/=pr[i];
			cnt[i]++;
		}
	}
	X=1ll*X*x%K;
}
void div(int x)
{
	if(X==0)return;
	for(int i=0;i<pn;i++)
	{
		while(x%pr[i]==0)
		{
			x/=pr[i];
			cnt[i]--;
		}
	}
	if(x>1)X=1ll*X*qpow(x,phi-1,K)%K;
}
int query()
{
	int ret=X;
	for(int i=0;i<pn;i++)
	{
		assert(cnt[i]<B);
		ret=1ll*ret*tab[i][cnt[i]]%K;
	}
	return ret;
}
int calc(int K)
{
	int inv2=(K+1)/2;
	b[0]=1ll*a[0]*inv2%K;
	for(int i=1;i<=2*M;i++)
	{
		b[i]=1ll*(a[i]-b[i-1])*inv2%K;
	}
	ll ret=0;
	for(int i=0;i<=M;i++)ret+=b[i*2];
	return (ret%K+K)%K;
}
int calc2(int K)
{
	for(int i=2*M+32;i>=0;i--)
	{
		b[i-1]=(a[i]-2ll*b[i])%K;
	}
	ll ret=0;
	for(int i=0;i<=M;i++)ret+=b[i*2];
	return (ret%K+K)%K;
}
int main()
{
	cin>>N>>M>>K;
	N=N/2+1;M=M/2;
	fac(K);
	X=1;
	for(int i=1;i<=2*M+32;i++)
	{
		if(2*N-i+1==0)break;
		mul(2*N-i+1);
		div(i);
		a[i-1]=query();
	}
	int d=0;
	if(pn>0&&pr[0]==2)d=pk[0];
	int K1=K/(1<<d),ans1=calc(K1);
	int K2=1<<d,ans2=calc2(K2);
	if(K1>K2)
	{
		swap(K1,K2);swap(ans1,ans2);
	}
	for(int i=0;i<K1;i++)
	{
		if((i*K2+ans2)%K1==ans1)
		{
			cout<<i*K2+ans2<<endl;
			return 0;
		}
	}
	return 0;
}

上一题