[NWRRC2015] Fygon 题解
这篇题解有点水。
因为只有六重循环,所以答案最多是关于
只需要求出
求点值直接暴力,而插值这里我采用了范德蒙德矩阵的逆,我直接打出了
注意分数类运算。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=45;
struct Frac {
Frac (int a=0,int b=0) {x=a,y=b;}
ll x,y;
}px[MAXN],py[MAXN],xs[MAXN];
int n,m,l,sj[MAXN],op[MAXN],ox[MAXN],oy[MAXN],nv[MAXN];
ll v[7][7]={ // 这表大概是范德蒙德逆矩阵的一个分子,具体的有点忘了
{720,-1764,1624,-735,175,-21,1},
{0,-720,1044,-580,155,-20,1},
{0,-360,702,-461,137,-19,1},
{0,-240,508,-372,121,-18,1},
{0,-180,396,-307,107,-17,1},
{0,-144,324,-260,95,-16,1},
{0,-120,274,-225,85,-15,1}};
ll b[7]={720,-120,48,-36,48,-120,720};
string s;
ll gcd (ll a,ll b) {return (b?gcd(b,a%b):a);}
Frac yf (Frac a) {
if (a.x==0) {a.y=1;return a;}
ll tmp=gcd(a.y,a.x);
a.y/=tmp,a.x/=tmp;
return a;
}
Frac add (Frac a,Frac b) {
ll tmp=gcd(a.y,b.y);
tmp=a.y/tmp*b.y;
Frac c;
c.y=tmp;
c.x=a.x*(tmp/a.y)+b.x*(tmp/b.y);
return yf(c);
}
Frac neg (Frac a) {
a.x*=-1,a.y*=-1;
return yf(a);
}
Frac minus (Frac a,Frac b) {
return yf(add(a,neg(b)));
}
Frac mult (Frac a,Frac b) {
Frac c;
c.x=a.x*b.x,c.y=a.y*b.y;
return yf(c);
}
Frac ds (Frac a) {
swap(a.x,a.y);
return yf(a);
}
Frac divs (Frac a,Frac b) {
return yf(mult(a,ds(b)));
}
int solve (int l,int r,int in) {
if (l==r) {return 1;}
int las=l,res=0;
for (int i=l+1;i<=r;i++) {
if (sj[i]==in) {
if (op[las]==1) {
for (int j=0;j<nv[oy[las]];j++) {
nv[ox[las]]=j;
res+=solve(las+1,i-1,in+1);
}
} else {
res++;
}
las=i;
}
}
if (op[las]==1) {
for (int j=0;j<nv[oy[las]];j++) {
nv[ox[las]]=j;
res+=solve(las+1,r,in+1);
}
} else {
res++;
}
//cout << l << " " << r << " " << res << endl;
return res;
}
int main () {
int nw=0;
while (getline(cin,s)) {
l=s.length();
int cur=0;
nw++;
while (s[cur]==' ') {
cur+=4;
sj[nw]++;
}
if (s[cur]=='l') {op[nw]=2;}
else {
op[nw]=1;
ox[nw]=s[cur+4]-'a'+10;
oy[nw]=(s[cur+15]>='a'&&s[cur+15]<='z')?(s[cur+15]-'a'+10):(s[cur+15]-'0');
}
}
for (int i=1;i<=9;i++) {nv[i]=i;}
for (int i=0;i<=6;i++) {
nv['n'-'a'+10]=i;
px[i]=Frac(i,1);
int tmp=solve(1,nw,0);
py[i]=Frac(tmp,1);
}
for (int i=0;i<=6;i++) {
xs[i].y=1;
for (int j=0;j<=6;j++) {
xs[i]=add(xs[i],divs(mult(py[j],Frac(v[j][i],1)),Frac(b[j],1)));
}
}
for (int j=6;j>=0;j--) {
if (xs[j].x<0) {
xs[j].x*=-1,xs[j].y*=-1;
}
if (xs[j].y<0) {printf("-");xs[j].y*=-1;}
else if (j<6) {printf("+");}
printf("%lld/%lld",xs[j].x,xs[j].y);
for (int k=1;k<=j;k++) {printf("*n");}
}
return 0;
}