题目链接:
http://www.bnuoj.com/v3/problem_show.php?pid=20172
题目大意:有C个模方程,每个方程可能有k余数,求最小的S个解。
解题思路:
看见模方程就想到中国剩余定理,然后看下确定的方程情况。
由乘法原理,共有II ki 种情况,即求解II ki 次。k比较大时基本完蛋。
其实解模方程还有一种暴力方法,就是选定一个模方程,令t=0,1...., n=t*LCM+余数(n一定要大于0)
通过t不断增大这种迭代方式从小到大创造一些可能解n,然后去测试其它方程,看余数对不对。
如果余数全对,那么就找到了一个解。否则就砍掉。
因为测试是很快的,大部分数据一开始就被砍了,所以k比较大时速度非常快。
毕竟上面是看RP的暴力,所以设定一个分界(10000),如果II ki <10000 ,那么还是通过中国剩余定理来求解,复杂度O(n)。
方法就是DFS枚举出C个余数情况,然后求解。
由于求出的全是最小整数解,S比较大时,剩余定理的解可能不足,这时候从小到大每个值加M的倍数凑出更大的解。
#include
"cstdio"
#include "set"
#include "vector"
#include "algorithm"
using namespace std;
#define LL long long
#define LIMIT 10000
int C,S,s;
LL m[15],k[
15],y[
15][
105],a[
15],M;
set value[15];
vector ans;
void solve_violence(int bc)
{
for(int i=1;i<=C;i++)
{
value[i].clear();
if(i!=bc) for(int j=1;j<=k[i];j++) value[i].insert(y[i][j]);
}
for(int t=0;S!=0;t++)
{
for(int i=1;i<=k[bc];i++)
{
LL n=t*m[bc]+y[bc][i];
if(!n) continue;
bool ok=true;
for(int j=1;j<=C;j++)
{
if(j==bc) continue;
if(!value[j].count(n%m[j])) {ok=false;break;}
}
if(ok) {printf("%lld
",n);if(--S==0) return;}
}
}
}
LL ex_gcd(LL a,LL b,LL &x,LL &y)
{
if(a==0&&b==0) return -1;
if(b==0) {x=1;y=0;return a;}
LL d=ex_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
LL solve_china()
{
LL res=0;M=1;
for(int i=1;i<=C;i++) M*=m[i];
for(int i=1;i<=C;i++)
{
LL w=M/m[i],x,y;
ex_gcd(m[i],w,x,y);
y=(y*w%M+M)%M;
res=(res+y*a[i])%M;
}
return res;
}
void dfs(int dep)
{
if(dep>C)
{
ans.push_back(solve_china());
return;
}
for(int i=1;i<=k[dep];i++)
{
a[dep]=y[dep][i];
dfs(dep+1);
}
}
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d%d",&C,&S)&&C)
{
int bestc=1;ans.clear();s=S;M=1;
LL tot=1;
for(int i=1;i<=C;i++)
{
scanf("%lld%lld",&m[i],&k[i]);
tot*=k[i];
if(k[i]*m[bestc]i;
for(int j=1;j<=k[i];j++) scanf("%lld",&y[i][j]);
sort(y[i]+1,y[i]+1+k[i]);
}
if(tot<LIMIT)
{
dfs(1);
sort(ans.begin(),ans.end());
for(int t=0;S!=0;t++)
for(int i=0;i)
{
LL n=t*M+ans[i];
if(n>0)
{
printf("%lld
",n);
if(--S==0) break;
}
}
}
else solve_violence(bestc);
printf("
");
}
}
neopenx
445520
20172
Accepted
GNU C++
26 ms
2223 B
2015-02-06 23:10:03