星星之火OIer:无关的元素

题目传送门(LGOJ)&&ZOJ&&UVAlife&&POJ&&UVA&&百练

为什么我们网站的数据这么水

又有1周没有出题解了,补一补

这道题,我们粗略的推一下,发现这里面的每一项合并之后是杨辉三角形里的第n行的每一个数,如图所示::

样例中的5,对应的是杨辉三角形的第五排,第五排中模3余0的只有第三个数

于是我们自然而然的想到去求杨辉三角

但我们会发现

题目给出的数据太大了

然后呢,因为这是排列组合的题

所以我们就会想到排列组合(废话)

但我们算杨辉三角不一定要递推

我们还可以用排列组合

而这里杨辉三角的第n排的第i个的值是  C(n,i)

进而又想起排列组合的另一个公式::

C(i,j)=\frac{i!}{(i-j)!*j!}

又可以推出::

C(i,j)=\frac{C(i,j-1)}{j}*(i-j+1)

因为::

\frac{C(i,j-1)}{j}*(i-j+1)=\frac{i!}{(j-1)!*(i-j+1)!*j}*(i-j+1)=\frac{i!}{j!*\frac{(i-j+1)!}{i-j+1}}=\frac{i!}{j!*(i-j)!}=C(i,j)

当然,这只是解题的一小部分

第100000排的杨辉三角形肯定是远远大于2147483647(INT_MAX)甚至远远大于9223372036854775807(LONGLONG_MAX)甚至有可能超过double和long double

所以投机取巧是不存在的

但是

我们有一种方法可以避免高精度运算

就是分解质因数

因为m<1000000000(10^9)

2*3*5*7*11*13*17*19*23*29=6469693230(6.469693230*10^9)

最多也只有10个质因子

而求质因子又有什么用呢??

我们想一想

如果m的质因子

这个数都有

且每一种质因子的个数都比m的大

那么这个数是不是一定是m的倍数???

我们假设m的质因子分解出来是:2,2,3,3,5,11,13,13

有一个数的质因子分解出来是:2,2,2,3,3,5,11,11,11,13,13

那么这个数一定能被m整除

而且这个数除以m一定是2*11*11=242

因为其他的都怼了嘛

用计算器算一下

m=334620

这个数=80978040

\frac{80978040}{334620}=242

所以这是一点

然后在最开始的地方用欧拉筛法筛出一个1~100000的素数表

就好了

下面是代码::

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=100000;
int p[10005],cnt;
bool h[N+5];//素数的记录
int n,m,c;
int mys[15],mgs[15],ngs[15],cmt;//mys是m(m)的因数(ys),mgs是m的因数的个数(gs),n代表当前数
void add(int a,int wh)
{
	for(int i=1;i<=cmt&&a>1;i++)
	{
		while(a%p[mys[i]]==0)
		{
			ngs[i]+=wh;//是m的质因子中的才用计算
			a/=p[mys[i]];
		}
	}
}
int main()
{
	for(int i=2;i<=N;i++)
	{
		if(!h[i])
			p[++cnt]=i;
		for(int j=1;j<=cnt&&i*p[j]<=N;j++)
			h[i*p[j]]=1;
	}//欧拉筛法是O(n)的,很快
	scanf("%d%d",&n,&m);
	n--;
	if(m==1){printf("0");return 0;}//任何数都是1的倍数
	for(int i=1;i<=cnt&&m>1;i++)//找m的质因子
	{
		if(m%p[i]==0)
		{
			mys[++cmt]=i;//第cmt种
			while(m%p[i]==0)
			{
				mgs[cmt]++;//个数++
				m/=p[i];
			}
		}
	}
	if(m>1){printf("0");return 0;}
	for(int i=1;i<=n;i++)
	{
		add(n-i+1,1);
		add(i,-1);//计算当前数的质因子个数
		int f=1;//标记
		for(int j=1;j<=cmt;j++)
		{
			if(ngs[j]<mgs[j])//不是m的倍数,上面推过的
			{
				f=0;//不存在,标记
				break;//终止循环
			}
		}
		if(f==1)//是m的倍数
		{
			c=1;//标记,至少一个无关
			printf("%d\n",i+1);
		}
	}
	if(!c){printf("0");return 0;}//全部有关
}

当然,这不是我的代码风格

这才是我的::

#include<cstdio>
inline void read(int &x) {
    x=0;
    int f=1;
    char s=getchar();
    while(s<'0'||s>'9') {
        if(s=='-')
            f=-1;
        s=getchar();
    }
    while(s>='0'&&s<='9') {
        x=x*10+s-48;
        s=getchar();
    }
    x*=f;
}
inline void pr(int x) {
    if(x<0) {
        putchar('-');
        x=-x;
    }
    if(x>9)
        pr(x/10);
    putchar(x%10+48);
}
int p[10005],cnt,n,m,c,mys[15],mgs[15],ngs[15],cmt;
bool h[100005];
inline void add(int a,int wh) {
    for(int i=1;i<=cmt&&a>1;i++)
        while(a%p[mys[i]]==0) {
            ngs[i]+=wh;
            a/=p[mys[i]];
        }
}
int main() {
    for(int i=2;i<=100000;i++) {
        if(h[i]==0)
            p[++cnt]=i;
        for(int j=1;j<=cnt&&i*p[j]<=100000;j++)
            h[i*p[j]]=1;
    }
    read(n),read(m);
    n--;
    if(m==1) {
        putchar(48);
        return 0;
    }
    for(int i=1;i<=cnt&&m>1;i++)
        if(m%p[i]==0) {
            mys[++cmt]=i;
            while(m%p[i]==0) {
                mgs[cmt]++;
                m/=p[i];
            }
        }
    if(m>1) {
        putchar(48);
        return 0;
    }
    for(int i=1;i<=n;i++) {
        add(n-i+1,1);
        add(i,-1);
        int f=1;
        for(int j=1;j<=cmt;j++)
            if(ngs[j]<mgs[j]) {
                f=0;
                break;
            }
        if(f==1) {
            c=1;
            pr(i+1),putchar('\n');
        }
    }
    if(!c)
        putchar(48);
}

思路来源于上面那个代码的码农

依然是一个同校大佬

谢谢支持!!!

weixin073智慧旅游平台开发微信小程序+ssm后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
python017基于Python贫困生资助管理系统带vue前后端分离毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值