ACM ICPC Dhaka Regional 2008: Stopping Doom's Day
2017, May 05
Tags: Polynomial Interpolation, Gaussian Elimination, Modular Inverse
Problem Statement:
Solution: One can probably find a closed form for this. But this is not necessary and also it can cause a lot of time-waste during a live contest. Instead, one can notice that, the term inside the summands is of degree 5. So, after all the summations are done, the final value is a 10 degree polynomial of $n$.
So, we can assume,
We can manually calculate the value of $f(n)$ for $n = 1, 2, \cdots, 11$. Then, it comes down to solving a system of 11 equations with 11 variables. We solve for the coefficients and use them to determine $f(n)$ for future values of $n$.
Implementation:
#include <bits/stdc++.h>
#define MOD 10007
using namespace std;
#define MAX 3
/// n rows, m columns
/// MAX is the maximum number of equations or variables
/// X holds the solution
/// returns 1 if unique solution, -1 if inconsistent, inf if infinite solutions
struct matrix{
long long arr[MAX+10][MAX+10];
int n, m;
void print()
{
for(int i = 0; i<n; i++)
{
for(int j = 0; j<=m; j++)
cout << arr[i][j] << " ";
cout << endl;
}
}
}A;
int where[MAX+10];
long long X[MAX+10];
const int inf = INT_MAX;
long long modinverse(long long a, long long n){
if(n==0) return 1LL;
long long ret = modinverse(a,n/2);
ret = (ret*ret) % MOD;
if(n%2==1){
ret = (ret*a) % MOD;
}
return ret;
}
int gauss()
{
memset(where,-1,sizeof(where));
int row, col;
for(row = col = 0; row<A.n && col<A.m; col++)
{
int pivot = row;
for(int i = row+1; i<A.n; i++)
{
if(abs(A.arr[pivot][col]) < abs(A.arr[i][col]))
pivot = i;
}
if(pivot != row)
{
for(int i = 0; i<=A.m; i++)
swap(A.arr[row][i], A.arr[pivot][i]);
}
if(A.arr[row][col]==0)
continue;
where[col] = row;
for(int i = row+1; i<A.n; i++)
{
if(A.arr[i][col])
{
long long c = (A.arr[i][col]*modinverse(A.arr[row][col],MOD-2))%MOD;
for(int j = col; j<=A.m; j++){
A.arr[i][j] -= (c*A.arr[row][j])%MOD;
A.arr[i][j] = (A.arr[i][j]+MOD)%MOD;
}
}
}
row++;
}
for(int i = 0; i<A.n; i++)
{
long long total = 0;
for(int j = 0; j<A.m;j++){
total += abs(A.arr[i][j]);
total %= MOD;
}
if(abs(total)==0 && abs(A.arr[i][A.m])==0)
return -1;
}
for(int i = A.n-1; i>=0; i--)
{
if(where[i] == -1) return inf;
int row = where[i];
long long sltn = A.arr[row][A.m];
for(int j = i+1; j<A.m; j++){
sltn -= (A.arr[row][j]*X[j])%MOD;
sltn %= MOD;
if(sltn < 0) sltn+= MOD;
}
X[i] = (sltn *modinverse(A.arr[row][i],MOD-2))%MOD;
}
return 1;
}
void buildmatrix(){
A.n = 11, A.m = 11;
for(int i = 0; i < A.n; i++){
A.arr[i][0] = 1LL;
for(int j = 1; j < A.m; j++){
A.arr[i][j] = (A.arr[i][j-1] * (i+1)) %MOD;
}
}
for(int n = 1; n <= 11; n++){
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
for(int k = 1; k <= n; k++){
for(int l = 1; l <= n; l++){
for(int m = 1; m <= n; m++){
A.arr[n-1][11] += ((long long)abs(i-j)*abs(j-k)*abs(k-l)*abs(l-m)*abs(m-i))%MOD;
A.arr[n-1][11] %= MOD;
}
}
}
}
}
}
}
long long Fun(long long n){
long long ret = X[10];
for(int i = 9; i >= 0; i--){
ret = (ret * n )%MOD+ X[i];
ret %= MOD;
}
return ret;
}
int main(){
buildmatrix();
int x = gauss();
long long n;
while(1){
scanf("%lld",&n);
if(n==0) break;
printf("%lld\n",Fun(n));
}
return 0;
}