数论 day3 crt lucas 十进制快速幂

今天考试有史以来最高:)

Mr. Ding 又来让你帮忙解方程了。
方程是这样的:
x1 + x1 + x3 + + xn = m (xi 0 81 i n)
Mr. Ding 希望你求出这个n 元一次方程的整数解有多少个,因为解的个数有可能变得很大,所以Mr.
Ding 只需要你输出解的个数取模于mod。
Input
第1 行,包含一个整数:T,表示询问个数
接下来T 行,每行包含三个整数:n m mod
Output

输出T 行,每行输出解的个数模对应mod

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=2005;
long long f[maxn],vf[maxn];
long long t,n,m,Mod;
void exgcd(long long a,long long b,long long &x,long long &y)
{
	if (b==0)
	{
		x=1;
		y=0;
		return ;
	}
	long long x1,y1;
	exgcd(b,a%b,x1,y1);
	x=y1;
	y=x1-(a/b)*y1;
}
long long inv(long long a,long long mod)
{
	long long x,y;
	exgcd(a,mod,x,y);
	return (x%mod+mod)%mod;
}
void init()
{
	f[0]=1;
	vf[0]=inv(f[0],Mod);
	for (int i=1;i<=n+m;i++){
		f[i]=f[i-1]*i;
		vf[i]=inv(f[i],Mod);
	}
}
int main()
{
	freopen("equation0.in","r",stdin);
	freopen("equation.out","w",stdout);
	scanf("%I64d",&t);
	while (t--)
	{
		scanf("%I64d%I64d%I64d",&n,&m,&Mod);
		init();
		printf("%I64d\n",f[n+m-1]*vf[n-1]%Mod*vf[m]%Mod);
	}
	return 0;
}
Mr. Ding 打算考一道比较显然的题目,低头一想,就有了这道题。
Mr. Ding 需要你计算:
3n mod 109 + 8
是不是很简单啊。^_^
Input
只有一行,一个数n。
Output

输出结果

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
long long p;
const int Mod=1e9+8;
char ch[100005];
long long mpow(long long a,long long b,long long mod)
{
	long rt=1;
	for (;b;b>>=1,a=a*a%mod)
	   if (b&1)
	      rt=rt*a%mod;
	return rt;
}
int main()
{
	freopen("power.in","r",stdin);
	freopen("power.out","w",stdout);
	scanf("%s",ch);
    int len=strlen(ch);
    reverse(ch,ch+len);
    long long ans=1;
    long long base=3;
    for (int i=0;i<len;i++)
    {
    	ans=ans*mpow(base,ch[i]-'0',Mod)%Mod;
    	base=mpow(base,10,Mod);
    }
    printf("%d\n",ans);
    return 0;
}
一天,Mr. Ding 对组合数产生了兴趣,他想要知道满足下面条件的数i 有多少个:
gcd(
(
n
i
)
; p) = p (0 i n)
其中p 是素数。
Input
第1 行,2 个整数:n p。
Output

输出所求。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
long long n,p;
int main()
{
	freopen("comb.in","r",stdin);
	freopen("comb.out","w",stdout);
	scanf("%I64d%I64d",&n,&p);
	long long ans=1;
	long long cmp=n+1;
	while (n)
	{
		ans*=n%p+1;
		n/=p;
	}
	printf("%I64d\n",cmp-ans);
	return 0;
}

最后一道题明显1e18有o(1)算法、

题目就是求c n i mod p==0

可以反向求不为0的情况,lucas定理将n化为p进制,由乘法原理得ans=(n1+1)*(n2+1)*.....(nk+1);

n+1-ans即为正确答案



猜你喜欢

转载自blog.csdn.net/beloved_rancy/article/details/79321803