noip2014解方程(真不知道那些大神怎么想到取模的,竟然考这个?!)

首先,这题需要负数取模(挺醉人的)

同时,我知道了取模与求余是不同的,http://blog.csdn.net/tedious/article/details/8777994

such as    a%b

具体来说,求模运算结果的符号和b一致,求余运算结果的符号和a一致。

正如:

求模运算和求余运算在第一步不同: 取模求余运算在取c的值时,向0 方向舍入(fix()函数);而求余取模运算在计算c的值时,向无穷小方向舍入(floor()函数)。因此,当a和b符号一致时,求模运算和求余运算所得的c的值一致,因此结果一致。但是当符号不一致的时候,结果不一样。

步入正题


<span style="font-family:KaiTi_GB2312;font-size:18px;">#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<string>
#include<cstring>
#include<cmath>

using namespace std;
typedef long long ll;
const int maxn=110;
const int prime[]={10007,11261,14843,19997,21893};
ll n,m;
ll stack[1001001],tot,a[maxn][5],f[30000][5];
void input(int x)//每个a【x】%prime【j】的余数 
{
	char s[10100];
	bool flag=false;
	scanf("%s",s+1);
	for (int i=1;s[i];i++)//s[i],这样的用法 ,表示读到'\0'结束啊0 0
	{
		if (s[i]=='-') flag=true;
		else 
		for (int j=0;j<5;j++)	
		a[x][j]=(a[x][j]*10 /*<=>(a[x][j]<<1)+(a[x][j]<<3)*/ +s[i]-'0')%prime[j];// pay attention to "s[i]-'0'"
	} 
	if (flag) 
	for (int j=0;j<5;j++)
	a[x][j]=prime[j]-a[x][j];//负数取模,负数模出来两个余数,一个正余数,一个负余数,负余数加模数==正余数 	
}
ll ff(int x,int j)
{
	ll ret=0;
	for (int i=n;~i;i--)//为什吗用  ~  
	ret=(ret*x+a[i][j])%prime[j];
	return ret;	
} 
int main()
{
	scanf("%lld%lld",&n,&m);
	for (int i=0;i<=n;i++) input(i);
	
	for (int j=0;j<5;j++)
	for (int i=0;i<prime[j];i++)
	f[i][j]=ff(i,j);//ans%prime【j】为i的答案是否符合,函数值返回的是方程左边计算值,若为0,就算符合
	
	for (int i=1;i<=m;i++)
	{
		int j;
		for (j=0;j<5;j++)
		if (f[i%prime[j]][j])break;
		if (j==5)//学习这种灵活的代码风格,代码能力要加强,学习大神们好的编码思路 
		stack[++tot]=i;
	}
	printf("%d\n",tot); 
	for (int i=1;i<=tot;i++)
	printf("%d\n",stack[i]);
	return 0; 
}</span>


你可能感兴趣的:(noip2014解方程(真不知道那些大神怎么想到取模的,竟然考这个?!))