POJ 3910 解题报告
这是个数学题
证明似乎没法用照片的形式了好悲伤啊
题目大意:
给你一个神奇的集合S,对于任意S内元素的值都满足一个神奇的条件:对于任意的x(是S中的元素),那么x/i也是(当然x/i要是整数)
这样啊,我不信我用不了文字来表达...
题目链接:http://poj.org/problem?id=3910
这一个文章我得好好解释一下啥是行列式了....
行列式的求解很复杂...
对于一个行列式,我们知道这么几个性质:
1,第i行可以整体减掉第j行的值,行列式值不变(就像高斯消元那样)(可以乘以k倍)(列好像也行)
2,对于一个除了对角线外全空的行列式,值为对角线的积
3,交换两行,值不变(列也一样)
那么我们来考虑这样一个问题
原题的a1,a2...an改为1,2...n
那么我来做点"合情合理的推理"
|(1,1) (1,2) (1,3) (1,4)|
|(2,1) (2,2) (2,3) (2,4)|
|(3,1) (3,2) (3,3) (3,4)|
|(4,1) (4,2) (4,3) (4,4)|
代码如下:
#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<string>
#include<time.h>
#include<math.h>
#include<memory>
#include<vector>
#include<bitset>
#include<fstream>
#include<stdio.h>
#include<utility>
#include<sstream>
#include<string.h>
#include<iostream>
#include<stdlib.h>
#include<algorithm>
using namespace std;
const int modo=1000000007;
int phi(int x)
{
int i;
int t=x;
for (i=2;i*i<=x;i++)
{
if (x%i==0)
{
t/=i;
t*=(i-1);
for (;x%i==0;)
{
x/=i;
}
}
}
if (x!=1)
{
t/=x;
t*=(x-1);
}
return t;
}
int main()
{
int n;
for (;scanf("%d",&n)!=-1;)
{
int i;
int p=1;
for (i=0;i<n;i++)
{
int x;
scanf("%d",&x);
p=(long long)p*phi(x)%modo;
}
printf("%d\n",p);
}
return 0;
}
可是呢...我们还没证明完呢怎么能放过这题??!!
考虑上面的矩阵,我们定义一个叫做a,一个叫做b
那么,我们定义
b(1,i) + b(2,i) + ... + b(n,i) = a(n,i)
以此得到b矩阵
我们要证明两点:
b(i,j) = 0 (j != ki,k是整数)
b(i,j) = phi(i) (j = ki)
那么首先,第一行显然是对的...
对于第i行,如果j!=ki的话
那么存在gcd(i,j)这么一行
满足b(1,j) + b(2,j) + ... + b((i,j),j) = (i,j)
那么剩下来的都不是j的因数,所以值都是0
所以b((i,j)+1,j) + ... + b(i,j) = 0所以值是0
那么b(i,j) = phi(i)也很好证明,因为sigma(d是i的约数,phi(i)) = i,所以直接反过来推即可
证明完毕
然而问题又来了..
题目给的是a1,a2...an而不是1,2...n
其实这个解决方案也很简单了啊...和上面证明是差不多的只要排个序就好了...(似乎给的性质还是很有用的)
大概真正和t有关的行全是t的约数的行,我们把所有别的行(和列)"抽掉"即可
例如
评论 (0)