スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

RUPC 2011

2011/10/15 13:00~17:00 (JST)
AOJ で開催された Ritsumeikan University Programming Contest の参加記録。

寝過ごしたので 30 分くらい遅れて参加。

Tags : プログラミング RUPC

結果

A. AC (00:37)
B. 4WA
C. AC (01:39)
D. WA, AC (02:04)
E. AC (03:17)
F. WA, AC (02:34)
G. -
H. -
I. -

Standing : 31/109


コンテスト中

コンテスト中に考えたことなど。

A. スワップ暗号

AOJ 侵略されとる…
復号したいので、素直に暗号の手順を逆にたどればいい。軽実装。

B. B問題

問題が理解できない。
2 回くらい心が折れかかった。

結局、最小の作業時間を申告した人だけに興味があるので、各人は ( ルールに違反しない ) できるだけ大きい数字を申告すると考えていい。
submit. WA.
最小作業時間がかぶった場合にどうなるのかがいまいち読み取れなかったので、その辺を適当に変えてみても WA.
何か反例を見逃しているのかと思い、問題文どおりにシミュレートするコードを書いてみたが、やっぱり WA.

あきらめて C に進むことにした。

C. Seishun 18 Kippu

2D 好きの彼のいる地点を経由して最短経路で目的地に行くだけなので、ただの Dijkstra でいいような気がする。
それだと簡単すぎるから何か見落としてるんじゃないかと思ったけど、特にそれらしいものは見当たらないので、とりあえず書く。
ノードが文字列なのでちょっとめんどう。
Dijkstra はライブラリぺたり。
書いた。サンプルがあったので submit. AC. これでいいのか…

D. 伝説の剣

これも入力のパースが若干アレだなぁ。

スタートとゴールと数字のあるマスをノードとして、
・ スタートから 1 に
・ k から k+1 に
・ 最大の数字からゴールに
有向辺を張った有向グラフに見える。
辺の重みは 2 ノード間のマンハッタン距離。
ちなみにこれは DAG になる。

各ノードについて、スタートからのそのノードまでの最短距離は、自分より 1 つ小さい数字からの遷移をみてやることで、DP で計算できる。

ほげ。

まだ壊せない宝石の上に乗ってもいいのかがわからなかったので、Clar でそれを聞いた ( つもりだった ) けど、結局よくわからなかった。自分の英文がおかしかったのかもしれない。
魔王を Maoh と英訳したのは私です。

E. アニペロ

シークレットアーティストは高々 2 人なので、最後にちょっと加えることにして、スタンダードアーティストについてだけ考える。
予算 LIMIT が小さいので、
dp[i][j][k] := i 人目のスタンダードアーティストまで見ていて、これまでに j 円使って k 人選んだときの最大満足度
がまず思いつく。

これだとメモリが厳しいようなので、1 次元分は配列を使いまわす。
dp[j][k] みたいな感じ。
0-1 ナップサックの要領なので、k は大きいほうから小さいほうへループを回さないといけない。
そうしないと、同じ人が何回でも使えるという状況になってしまう。

dp 配列が全部埋まったら、n2 通り程度のシークレットアーティストの組み合わせを全部試す。
この部分が計算量多めでちょっと危ないかなと思ったけど、submit してみたら普通に間に合った。

※ 下に載せたコードとは添え字の対応が違うので、読みたい人は注意

F. Farey Sequence

ファレイ数列ってあれでしょー分母どうし分子どうし足してもいいやつ!! とか一人で盛り上がる。

分母を 1, 2, 3, ... と動かしたときに、重複カウントしないということは、分母と互いに素な分子だけを考えるということだから、Euler の φ 関数そのもの。
これは篩のアルゴリズムを応用すれば、わりと大きな値まで計算して持っておくことができる。

答えはそれの累積和なので、DP 的な前処理をやっておく。これで各クエリ O(1) になる。

あってる自信があったのに WA でびっくりした。
色々テストしていたら、どうやら φ の値を求める処理にバグがあるらしいということがわかった。
蟻本のコードと目で diff を取ってみると、外のループが √n までしか動いてなかった。

修正して submit. AC.

G. 水時計

Water Tank を髣髴とさせる超シミュレーションゲーに見える。
残り時間が 1 時間を切っていて、書ききれるはずもなかったのでパス。

H. Oh, My Goat!

難しい。
アルゴリズムが思いつかなかった。

I. カスタムペイント職人

アルゴリズム自体は一瞬で見えて、がんばって実装すれば解けそうな問題だった。
結局、コンテスト中は B に固執していたので取り組まなかった。

AOJ に似た問題 ( 円形のシールを貼る ) があったはず。



作題おつかれさまでした。
この問題セットはもともと合宿用に作られたということですが、こういう形で公開されるのはとても良いと思いました。
tricky な問題が少なく、堅実な、基礎を押さえていれば手がつけられるような問題が多かったという印象でした。

ソースコード

A.
int main(){
for(int n;scanf("%d",&n),n;){
char s[101]; scanf("%s",s);
int a[100],b[100];
rep(i,n) scanf("%d%d",a+i,b+i), a[i]--, b[i]--;

for(int i=n-1;i>=0;i--){
int d=b[i]-a[i];
s[a[i]]=(s[a[i]]-'a'+d)%26+'a';
s[b[i]]=(s[b[i]]-'a'+d)%26+'a';
swap(s[a[i]],s[b[i]]);
}

puts(s);
}

return 0;
}


B. ( あとで解いた )
int main(){
for(int n,m;scanf("%d%d",&n,&m),n;){
int t=INF,pre,ans,cnt=0;
rep(i,n){
int a; scanf("%d",&a);

int j;
for(j=m;j%a;j--);

if(j<t || (j==t && a<=pre)){
cnt=(j==t&&a==pre?cnt+1:1);
t=j;
pre=a;
ans=i;
}
}

printf("%d\n",cnt<2?ans+1:n);
}

return 0;
}

終わってから twitter で問題解釈を教えてもらって、ゼロから書き直したら一発で通った。
前のコードのどこが悪かったのかは不明。

C.
template<class T> struct Edge{
int u,v;
T w;
Edge(int U,int V,T W):u(U),v(V),w(W){}
};

template<class T>
struct AdjList:public vector< vector< Edge<T> > >{
AdjList(int n,const vector< Edge<T> > &v=vector< Edge<T> >()):vector< vector< Edge<T> > >(n,v){}
};

template<class T>
T Dijkstra(const AdjList<T> &adj,int s,int t){
int n=adj.size();
vector<T> d(n,INF); d[s]=0;

priority_queue< pair<T,int> > pq; pq.push(make_pair(0,s));
while(!pq.empty()){
pair<T,int> a=pq.top(); pq.pop();
int u=a.second;
if(d[u]<-a.first) continue;
if(u==t) break;

rep(i,adj[u].size()){
int v=adj[u][i].v;
T w=adj[u][i].w;
if(d[u]+w<d[v]){
d[v]=d[u]+w;
pq.push(make_pair(-d[v],v));
}
}
}

return d[t];
}

int main(){
for(int n,m;scanf("%d%d",&n,&m),n;){
int n2=0;
map<string,int> f;

int pos[3];
rep(i,3){
char s[1025]; scanf("%s",s);
pos[i]=f[s]=n2++;
}

AdjList<int> adj(n);
rep(_,m){
char s1[1025],s2[1025];
int u,v,d,t; scanf("%s%s%d%d",s1,s2,&d,&t);
if(f.count(s1)==0) f[s1]=n2++;
if(f.count(s2)==0) f[s2]=n2++;
u=f[s1];
v=f[s2];
adj[u].push_back(Edge<int>(u,v,d/40+t));
adj[v].push_back(Edge<int>(v,u,d/40+t));
}

printf("%d\n",Dijkstra(adj,pos[0],pos[1])+Dijkstra(adj,pos[1],pos[2]));
}

return 0;
}

入力以外はほぼライブラリ。

D.
const int INF=1<<29;

struct P{ int x,y,cost; };

int main(){
for(int w,h;scanf("%d%d",&w,&h),w;){
int B[100][100];
int sx,sy,gx,gy;
int lastdgt=0;
vector<P> dgt[10010];
rep(i,h) rep(j,w) {
char ss[16]; scanf("%s",ss);
if(!isdigit(ss[0])) B[i][j]=0;
else sscanf(ss,"%d",&B[i][j]);

if(ss[0]=='S') sx=j, sy=i;
if(ss[0]=='G') gx=j, gy=i;
if(isdigit(ss[0])){
dgt[B[i][j]].push_back((P){j,i,INF});
lastdgt=max(lastdgt,B[i][j]);
}
}
dgt[ 0 ].push_back((P){sx,sy,0});
dgt[lastdgt+1].push_back((P){gx,gy,INF});

rep(k,lastdgt+1){
rep(i,dgt[k].size()) rep(j,dgt[k+1].size()) {
P p=dgt[k][i],q=dgt[k+1][j];
dgt[k+1][j].cost=min(q.cost,p.cost+abs(q.x-p.x)+abs(q.y-p.y));
}
}
printf("%d\n",dgt[lastdgt+1][0].cost);
}

return 0;
}


E.
const int INF=1<<29;

int main(){
for(int lim,n,m,x;scanf("%d%d%d%d",&lim,&n,&m,&x),lim;){
int e_sec[100],s_sec[100];
rep(i,n) scanf("%*s%d%d",e_sec+i,s_sec+i);
int e[100],s[100];
rep(i,m) scanf("%*s%d%d",e+i,s+i);

int dp[101][1001]; // dp[i][j] := i 人, j 円使ったときの最大満足度
rep(i,m+1) rep(j,lim+1) dp[i][j]=-INF;
dp[0][0]=0;
rep(i,m) for(int k=i;k>=0;k--) for(int j=e[i];j<=lim;j++) {
dp[k+1][j]=max(dp[k+1][j],dp[k][j-e[i]]+s[i]);
}

int ans=-INF;
for(int i=x;i<=m;i++) rep(j,lim+1) if(dp[i][j]>=0) {
int tmp=-INF;
rep(k,n){
if(j+e_sec[k]<=lim) tmp=max(tmp,s_sec[k]);
rep(l,k) if(j+e_sec[k]+e_sec[l]<=lim) tmp=max(tmp,s_sec[k]+s_sec[l]);
}
ans=max(ans,dp[i][j]+tmp);
}
printf("%d\n",ans);
}

return 0;
}


F.
int main(){
const int Np=1000000;
static int phi[Np+1];
rep(i,Np+1) phi[i]=i;
for(int i=2;i<=Np;i++) if(phi[i]==i) {
for(int j=i;j<=Np;j+=i) phi[j]=phi[j]/i*(i-1);
}

static ll dp[Np+1];
rep(i,Np) dp[i+1]=dp[i]+phi[i+1];

int T; scanf("%d",&T);
while(T--){
int n; scanf("%d",&n);
printf("%lld\n",dp[n]+1);
}

return 0;
}


G. ( あとで解いた )
const int dx[]={1,0,-1,0},dy[]={0,-1,0,1};

class union_find{
vector<int> a;
public:
union_find(int n):a(n,-1){}
int find(int x){
if(a[x]<0) return x;
return a[x]=find(a[x]);
}
void unite(int x,int y){
x=find(x),y=find(y);
if(x!=y){ a[x]+=a[y]; a[y]=x; }
}
int size(int x){ return -a[find(x)]; }
};

int w,h,B[12][12];

int nf,f[12][12]; // マージ後の水槽の個数, マージ後の水槽の番号
vector<int> next[144]; // 水槽 i の水の流れる先

void dfs(int i,int j,bool vis[12][12]){
vis[i][j]=true;
rep(k,4){
int y=i+dy[k],x=j+dx[k];
if(0<=y && y<h && 0<=x && x<w){
if(!vis[y][x] && B[i][j]==B[y][x]){
dfs(y,x,vis);
}
else if(B[i][j]>B[y][x]){
next[f[i][j]].push_back(f[y][x]);
}
}
}
}

int main(){
for(;scanf("%d%d",&w,&h),w;){
int fx,fy,fq; scanf("%d%d%d",&fx,&fy,&fq); fx++; fy++;
rep(i,h+2) B[i][0]=B[i][w+1]=0;
rep(j,w+2) B[0][j]=B[h+1][j]=0;
rep(i,h) rep(j,w) scanf("%d",B[i+1]+j+1);
h+=2; w+=2;

// 同じ高さの水槽をマージ
union_find U(h*w);
rep(i,h) rep(j,w) rep(k,4) {
int y=i+dy[k],x=j+dx[k];
if(0<=y && y<h && 0<=x && x<w && B[i][j]==B[y][x]) U.unite(i*w+j,y*w+x);
}

// 水槽の番号を正規化
nf=0;
int tmp[144];
rep(u,h*w) tmp[u]=-1;
rep(i,h) rep(j,w) if(tmp[U.find(i*w+j)]==-1) tmp[U.find(i*w+j)]=nf++;
rep(i,h) rep(j,w) f[i][j]=tmp[U.find(i*w+j)];

int hh[144]; // hh[u] := 水槽 u の高さ
int sz[144]; // sz[u] := 水槽 u がいくつの水槽をマージしてできたか
rep(i,h) rep(j,w) {
hh[f[i][j]]=B[i][j];
sz[f[i][j]]=U.size(i*w+j);
}

// 水の流れの有向グラフを構築
rep(u,nf) next[u].clear();
bool vis[12][12]={};
rep(i,h) rep(j,w) if(!vis[i][j]) dfs(i,j,vis);

int nq; scanf("%d",&nq);
while(nq--){
int qt,qx,qy; scanf("%d%d%d",&qt,&qx,&qy); qx++; qy++;

int s=f[fy][fx],t=f[qy][qx]; // 蛇口のある水槽, 観測する水槽
double water[144]={};
water[s]=fq*qt; // s に水を流量 fq で qt 秒間流す

priority_queue< pair<int,int> > Q;
rep(u,nf) Q.push(make_pair(hh[u],u));

while(!Q.empty()){ // 高い順に取り出す
int u=Q.top().second; Q.pop();

double over=max(water[u]-sz[u]*30*30*30,0.0); // あふれた水量
water[u]=min(water[u],sz[u]*30*30*30.0);

rep(i,next[u].size()){
int v=next[u][i];
water[v]+=over/next[u].size();
}
}

printf("%d\n",(int)(water[t]/(sz[t]*30*30)));
}
}

return 0;
}

[ 2012/02/06 追記 ]

解説スライドを見ながら解いた。
グラフを作るところまでは DFS + α でやった。
各クエリの処理は高い水槽から順に全部なめていくようにした。

デバッグが大変だった。
はまった点は
・ クエリの処理を priority_queue ではなく普通の queue で書いたために、水槽を見る順番を間違えた
・ フィールドの周り 1 マスを 0 で埋めて 12 × 12 マスで考えていたんだけど、その増やしたマスの初期化を忘れた

H. ( あとで解いた )
const int M=1000000007;

struct edge{
int u,v,id;
string s;
};

int n1,n2;
edge E1[600],E2[600];
vector<int> adj1[500],adj2[500];

// dp[i1][i2][p2] := DAG 1 では辺 i1 の 0 文字目を、
// DAG 2 では辺 i2 の p2 文字目をみている状態での解 (以降、一致する文字列の個数)
int dp[600][600][6];
int dfs(int i1,int i2,int p1,int p2){
int dummy,&res=(p1==0?dp[i1][i2][p2]:dummy);
if(p1==0 && ~res) return res;

// 2 つのポインタが同時に DAG の終端に来た
if(p1==E1[i1].s.length() && p2==E2[i2].s.length()){
int v1=E1[i1].v,v2=E2[i2].v;
if(v1==n1-1 && v2==n2-1) return res=1;
}

// ポインタ 1 が文字列終端に来た
if(p1==E1[i1].s.length()){
int v=E1[i1].v,cnt=0;
rep(k,adj1[v].size()) cnt=(cnt+dfs(adj1[v][k],i2,0,p2))%M;
return res=cnt;
}

// ポインタ 2 が文字列終端に来た
if(p2==E2[i2].s.length()){
int v=E2[i2].v,cnt=0;
rep(k,adj2[v].size()) cnt=(cnt+dfs(i1,adj2[v][k],p1,0))%M;
return res=cnt;
}

// 指している文字が違うなら探索打ち切り
if(E1[i1].s[p1]!=E2[i2].s[p2]) return res=0;

return res=dfs(i1,i2,p1+1,p2+1);
}

int main(){
int T; cin>>T;
while(T--){
memset(dp,-1,sizeof dp);
int m1; cin>>n1>>m1;
rep(u,n1) adj1[u].clear();
rep(j,m1){
int u,v;
string s; cin>>u>>v>>s;
adj1[u].push_back(j);
E1[j]=(edge){u,v,j,s};
}
int m2; cin>>n2>>m2;
rep(u,n2) adj2[u].clear();
rep(j,m2){
int u,v;
string s; cin>>u>>v>>s;
adj2[u].push_back(j);
E2[j]=(edge){u,v,j,s};
}

int ans=0;
rep(i,adj1[0].size()) rep(j,adj2[0].size()) {
ans=(ans+dfs(adj1[0][i],adj2[0][j],0,0))%M;
}
printf("%d\n",ans);
}

return 0;
}

[ 2012/01/09 追記 ]
解説スライドを見た。
解法を知ってしまうと、( 少なくとも大まかは方針は ) とても素直な問題に見える。これが解けなかったのはダメだなぁ。

自分のコードは解説のものとは少しだけ違って、dp[600][600][5] くらいでメモ化してある。
何をやっているのかはコメントに書いた。
いずれにせよ、MLE 回避のためにどうにかしてメモ化をさぼるのがポイントなんだと思う。

I. ( あとで解いた )
typedef complex<double> Point;

const double EPS=1e-9;
const double PI=acos(-1);

class Line:public vector<Point>{
public:
Line(){}
Line(const Point &a,const Point &b){ push_back(a), push_back(b); }
};

class Segment:public Line{
public:
Segment(const Point &a,const Point &b):Line(a,b){}
};

class Circle{
public:
Point c;
double r;
Circle(){}
Circle(const Point &C,double R):c(C),r(R){}
};

class Sector:public Circle{
public:
double t1,t2;
};

inline double dot(const Point &a,const Point &b){
return a.real()*b.real()+a.imag()*b.imag();
}

inline double cross(const Point &a,const Point &b){
return a.real()*b.imag()-a.imag()*b.real();
}

inline void calc_abc(const Line &l,double &a,double &b,double &c){
a=l[0].imag()-l[1].imag();
b=l[1].real()-l[0].real();
c=cross(l[0],l[1]);
}

Point PerpFoot(const Point &p,const Line &l){
double a,b,c;
calc_abc(l,a,b,c);
Point v(a,b);
return p-(dot(p,v)+c)*v/norm(v);
}

bool cover(const Segment &s,const Point &p){
return dot(s[0]-p,s[1]-p)<EPS;
}

bool intersect(const Line &l,const Line &m,Point &p){
if(abs(cross(l[1]-l[0],m[1]-m[0]))>EPS
|| abs(cross(l[1]-l[0],m[0]-l[0]))<EPS){
double a1,b1,c1,a2,b2,c2;
calc_abc(l,a1,b1,c1);
calc_abc(m,a2,b2,c2);
double det=a1*b2-a2*b1;
if(abs(det)<EPS) p=l[0]; // l==m
else p=Point(b1*c2-b2*c1,a2*c1-a1*c2)/det;
return true;
}
return false;
}

int intersect(const Circle &c,const Line &l,Point &p,Point &q){
Point m=PerpFoot(c.c,l);
double d=abs(c.c-m);
if(c.r+EPS<d) return 0;
else if(abs(c.r-d)<EPS){
p=q=m;
return 1;
}
else{
Point v;
double n0=norm(l[0]-m),n1=norm(l[1]-m);
if(n0<n1) v=l[1]-m, n0=n1;
else v=l[0]-m;
v*=sqrt((c.r*c.r-d*d)/n0);
p=m+v, q=m-v;
return 2;
}
}

int intersect(const Circle &c,const Segment &s,Point &p,Point &q){
Point pp,qq;
int n=intersect(c,Line(s),pp,qq);
if(n==0) return 0;
else if(n==1){
if(cover(s,pp)){
p=q=pp;
return 1;
}
return 0;
}
else{
bool bp=cover(s,pp),bq=cover(s,qq);
if(bp&&bq){
p=pp, q=qq;
return 2;
}
if(bp||bq){
p=q=(bp?pp:qq);
return 1;
}
return 0;
}
}

int intersect(const Circle &c1,const Circle &c2,Point &p,Point &q){
double d=abs(c1.c-c2.c);
if(d<EPS && abs(c1.r-c2.r)<EPS) return -1; // c1==c2
if(c1.r+c2.r<d-EPS || d+EPS<abs(c1.r-c2.r)) return 0;

if(abs(c1.r+c2.r-d)<EPS){
intersect(c1,Segment(c1.c,c2.c),p,q);
return 1;
}

double a=(c1.r*c1.r-c2.r*c2.r+d*d)/(2*d);
double h=sqrt(c1.r*c1.r-a*a);
p=q=c1.c+a/d*(c2.c-c1.c);
Point tmp=h*(c2.c-c1.c)/d;
p+=tmp*Point(0,-1);
q+=tmp*Point(0,+1);
return 2;
}

void intersect(const Sector &S1,const Sector &S2,vector<Point> &P){
Point Q,R;
Line L1(S1.c,S1.c+polar(1.0,S1.t1));
Line M1(S1.c,S1.c+polar(1.0,S1.t2));
Line L2(S2.c,S2.c+polar(1.0,S2.t1));
Line M2(S2.c,S2.c+polar(1.0,S2.t2));
Circle C1(S1),C2(S2);

if(intersect(C1,C2,Q,R)>0) P.push_back(Q), P.push_back(R);
if(intersect(C1,L2,Q,R)>0) P.push_back(Q), P.push_back(R);
if(intersect(C1,M2,Q,R)>0) P.push_back(Q), P.push_back(R);
if(intersect(C2,L1,Q,R)>0) P.push_back(Q), P.push_back(R);
if(intersect(C2,M1,Q,R)>0) P.push_back(Q), P.push_back(R);
if(intersect(L1,L2,Q)>0) P.push_back(Q);
if(intersect(L1,M2,Q)>0) P.push_back(Q);
if(intersect(M1,L2,Q)>0) P.push_back(Q);
if(intersect(M1,M2,Q)>0) P.push_back(Q);
}

bool cover(const Circle &c,const Point &p){
return abs(p-c.c)<c.r+EPS;
}

bool cover(const Sector &S,const Point &P){
if(abs(S.c-P)<EPS) return true;
if(!cover(Circle(S),P)) return false;

double a1=arg(polar(1.0,S.t1));
double a2=arg(polar(1.0,S.t2));
double ap=arg(P-S.c);
if(a2<a1-EPS) a2+=2*PI;
if(ap<a1-EPS) ap+=2*PI;
return a1-EPS<ap && ap<a2+EPS;
}

int main(){
int T; scanf("%d",&T);
while(T--){
int n; scanf("%d",&n);
Sector S[16];
rep(i,n){
int x,y,t1,t2; scanf("%d%d%lf%d%d",&x,&y,&S[i].r,&t1,&t2);
S[i].c=Point(x,y);
S[i].t1=PI*t1/180;
S[i].t2=PI*t2/180;
}

vector<Point> P;
rep(i,n){
P.push_back(S[i].c);
for(int j=i+1;j<n;j++) intersect(S[i],S[j],P);
}

int ans=0;
rep(i,P.size()){
int cnt=0;
rep(j,n) if(cover(S[j],P[i])) cnt++;
ans=max(ans,cnt);
}
printf("%d\n",ans);
}

return 0;
}

「重なりが最大になりそうな点 ( 候補点 ) をすべて調べる」 という方針。
候補点は、2 つの扇形の境界の交点と、各扇形内の任意の 1 点。
後者は、大きい扇形が小さい扇形を含むというケースがあるので必要。sample 3 参照。

2 つの扇形の交点は、円と円の交点、円と直線の交点、直線と直線の交点を全部含めた。
それらの点が本当に扇形の交点かどうか調べるのは大変だし、候補点を多く取る分には問題ないので。

ある点 P が扇形 S に含まれるかどうかの判定は、
(1) P が S の中心に一致していれば含まれる
(2) P が S を延長してできる円より外にあれば含まれない
(3) S の中心から P へいたるベクトルの偏角を調べて、それが S の 2 つの半径 (?) の間にあるかを調べる
の順でやった。
ゼロベクトルの偏角を測らないようにするために、(1) は必要。

円と円の交点、円と直線の交点、直線と直線の交点などはすべて幾何ライブラリから貼り付け。
私の幾何ライブラリは関数の間の依存度が大きいので、コード量は多くなりがち。

さすがに扇形ライブラリは持っていないので、そこはまじめに書いた。
スポンサーサイト

コメントの投稿

非公開コメント

プロフィール

fura2

Author : fura2
数学・コンピュータを中心に、考えたこと・やったことを書いていきます。

誤植等を含め、間違いはご指摘いただければ幸いです。

FC2カウンター
検索フォーム
最新記事
最新コメント
最新トラックバック
月別アーカイブ
リンク
RSSリンクの表示
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。