• [NOIP2014] 解方程


    题目描述

    已知多项式方程:

    [a_0+a_1x+a_2x^2+⋯+a_nx^n=0 ]

    求这个方程在 [1,m] 内的整数解(n 和 m均为正整数)。

    输入输出格式

    输入格式:

    共 n+2行。

    第一行包含 2 个整数 n,m,每两个整数之间用一个空格隔开。

    接下来的 n+1行每行包含一个整数,依次为 a0,a1,a2…an。

    输出格式:

    第一行输出方程在 [1,m] 内的整数解的个数。

    接下来每行一个整数,按照从小到大的顺序依次输出方程在 [1,m] 内的一个整数解。

    输入输出样例

    输入样例#1:

    2 10
    1
    -2
    1

    输出样例#1:

    1
    1

    输入样例#2:

    2 10
    2
    -3
    1

    输出样例#2:

    2
    1
    2

    输入样例#3:

    2 10
    1
    3
    2

    输出样例#3:

    0

    说明

    对于 30% 的数据:(0<n≤2,∣a_i∣≤100,a_n≠0,m<100).
    对于 50% 的数据:(0<n≤100,∣a_i∣≤10^{100},a_n≠0,m<100)
    对于 70% 的数据:(0<n≤100,∣a_i∣≤10^{10000},a_n≠0,m<10^4)
    对于 100% 的数据:(0<n≤100,∣a_i∣≤10^{10000},a_n≠0,m<10^6)

    Solution

    首先我们得明白一条性质,如果我们选一个质数p,如果枚举x,发现多项式结果ans%p≠0,那么我们就能肯定x不是解,因为如果是解,那么多项式答案应该为0,但是0模任何数(除0之外)都为0,而此时发现模p不等于0,那么显然x不是解,看一波复杂度,O(NM)貌似可以过70分。继续想,
    既然x不是解那么显然x+p也不是解,这样问题就解决了。
    prime[i],代表第i个质数是什么。
    但是又不能枚举去筛,那复杂度又上去了,所以可以用数组存下来,(vis[i][j])代表i这个数取模第j个质数不等于0,那么到时枚举解x时,只需判断(vis[x~~mod ~~prime[j]][j])是否等于0就行了,为了怕出错,多选几个质数就行了。
    本题数据范围这么大,有点操蛋,这是要写高精度的节奏,死活不打。
    发现可以一边读入一边取模。
    这题数据有点强,卡1~200所有质数,所以我就选了一千多的质数。
    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef unsigned long long ll;
    char s[101][10010];
    ll prime[]={2,7,9,11,103,1597,1601,1607,1609,1613,1619,1621,1627};
    ll real[1010000],kzj=0;
    ll p[110][20],vis[120][20];
    ll ans[1001010];
    ll check(char *ss,ll mod)
    {
    	ll flag=1,tot=0,x=0;char ch=ss[0];
    	ll len=strlen(ss);
    	if(ch<'0'||ch>'9') if(ch=='-') flag=-1,tot++,ch=ss[1];
    	while(ch<='9'&&ch>='0') 
    	{
    		x=((x*10)%mod+(ch-48))%mod;
    		ch=ss[++tot];
    		if(tot==len)
    		break;
    	}
    	return (x*flag+mod)%mod;
    }
    int main()
    {	
    //	freopen("xuanxue.in","r",stdin);
    //	freopen("xuanxue.out","w",stdout);
    	ll n,m;
    	cin>>n>>m;
    	n++;
    	for(ll i=1;i<=n;i++)
    	scanf("%s",s[i]);
    	for(ll i=1;i<=n;i++)
    	{
    		for(ll j=0;j<=12;j++)
    		p[i][j]=check(s[i],prime[j]);
    	}
    	for(ll i=1;i<=1700;i++)
    	{
    		ll flag=0;
    		for(ll j=0;j<=12;j++)
    		{
    			ll k=1,sum=0;
    			ll mod=prime[j];
    			for(ll t=1;t<=n;t++)
    			{
    				sum=(sum%mod+p[t][j]%mod*k%mod)%mod;	
    				k=k*i%mod;
    			}
    			if(sum!=0) 
    			{
    				vis[i][j]=1;
    			}
    		}
    	}
    	for(ll i=1;i<=m;i++)
    	{
    		ll flag=0;
    		for(ll j=0;j<=12;j++)
    		if(vis[i%prime[j]][j]==1)
    		flag=1;
    		if(!flag) real[++kzj]=i;
    	}
    	cout<<kzj<<endl;
    	for(ll i=1;i<=kzj;i++)
    	printf("%lld
    ",real[i]);
    }
    
  • 相关阅读:
    内功心法-代理模式
    java.lang.NumberFormatException: multiple points
    MarkDown语法-使用博客园的markDown编辑
    MarkDown语法
    linux下安装tomcat——service tomcat does not support chkconfig
    关于git&github的操作
    activeMQ 本地测试
    spring AOP 的坑~
    js高级面试题
    js的内存管理
  • 原文地址:https://www.cnblogs.com/kzj-pwq/p/9567313.html
Copyright © 2020-2023  润新知