[HNOI2006]马步距离

61.187.179.132:8080/JudgeOnline/showproblem
数据那么大暴搜只能去死。。
我想先贪心的跳一会,当距离比较近的时候再暴搜。
我一开始想的贪心是直接按距离。。结果WA。。
然后我编数据找原因。。发现对于那些正方形两个对角点比如0 0 100 100的数据错的很厉害。。
然后我感觉似乎是因为这样贪心的话一开始就会往边上跳。。不顾后来的情况。
所以我又加了个指标就是如果距离一样,那么横纵距离差小的更有优先权。就A掉了。
Code:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<cstring>
#include<queue>
#define rep(i,n) for(int i=0;i<n;i++)
#define pb push_back
using namespace std;
typedef pair<int,int> pi;
const pi D[]={pi(2,1),pi(1,2),pi(-1,2),pi(-2,1),pi(-2,-1),pi(-1,-2),pi(1,-2),pi(2,-1)};
const int inf=~0U>>1;
inline int abs(int x){return x<0?-x:x;}
inline pi dist(pi a,pi b)
{
int x=abs(a.first-b.first),y=abs(a.second-b.second);
return pi(x+y,abs(x-y));
}
pi operator+(const pi&a,const pi&b)
{
return pi(a.first+b.first,a.second+b.second);
}
ostream& operator<<(ostream& out,const pi&a)
{
out<<"("<<a.first<<","<<a.second<<")";
}
int main()
{
//freopen("in","r",stdin);
pi a,b;int ans=0;
cin>>a.first>>a.second>>b.first>>b.second;
while (dist(a,b).first>10)
{
pi next,Min(inf,inf);
rep(i,8)
{
pi c=a+D[i];pi ncost=dist(c,b);
if(ncost<Min)
Min=ncost,next=c;
}
a=next,ans++;
}
int x=min(a.first,b.first),y=min(a.second,b.second);
pi c=pi(-x,-y);
a=a+c+pi(5,5);b=b+c+pi(5,5);
bool vis[100][100]={0};
int d[100][100];
vis[a.first][a.second]=true;
d[a.first][a.second]=0;
queue<pi> Q;Q.push(a);
while (Q.size())
{
pi t=Q.front();Q.pop();int cost=d[t.first][t.second];
if(t==b) break;
rep(i,8)
{
pi c=t+D[i];
if(c.first>=0&&c.first<100&&c.second>=0&&c.second<100)
if(!vis[c.first][c.second])
{
vis[c.first][c.second]=true;
d[c.first][c.second]=cost+1;
Q.push(c);
}
}
}
cout<<ans+d[b.first][b.second];
}

[HNOI2006]超级英雄Hero

61.187.179.132:8080/JudgeOnline/showproblem
太TMD恶心了。。一眼就看出是匹配。。关键是这个答题是要连续的!
也就是说从1到开始找增广轨找不到就不能再找了。。结果WA了3次
Code:
#include<iostream>
#define rep(i,n) for(int i=0;i<n;i++)
using namespace std;
const int V=1200;
int E[V][2],Link[V],n,m;
bool vis[V];
bool dfs(int x)
{
if(vis[x]) return 0;
vis[x]=1;
for(int i=0,t;i<2;i++)
{
t=E[x][i];
if(Link[t]==-1||dfs(Link[t]))
return Link[t]=x,1;
}
return 0;
}
int main()
{
cin>>n>>m;
rep(i,m) cin>>E[i][0]>>E[i][1];
rep(i,n) Link[i]=-1;
int ans;
for(ans=0;ans<m;ans++){memset(vis,0,sizeof(vis)); if(!dfs(ans)) break;}
cout<<ans<<endl;
}

【VIJOS 1549】 中位数

www.vijos.cn/Problem_Show.asp
也是[CQOI2009]中位数图
额。。设b所在位置为x,
设一个数列S中大于b的数的数量-小于b的数的数量F(S)
那么这个序列由x左边的一些和右边的一些构成,且F(Left)+F(Right)=0。。
那么就很简单了。。从x往右扫描一遍,记录每个F(S)出现了几次,放在Count数组里
再往左扫描一遍,若当前F值为now,只要把答案+上Count[-now]就可以了
0ms1A。。真是爽啊。。
Code:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<cstring>
#define rep(i,n) for(int i=0;i<n;i++)
#define pb push_back
using namespace std;
const int inf=~0U>>1;
const int maxn=1e5+10;
int main()
{
//freopen("in","r",stdin);
int n,b;int A[maxn];
int C[maxn*2]={0};
cin>>n>>b;int x;
rep(i,n) scanf("%d",A+i),x=(A[i]==b?i:x);
int now=0;
C[now+maxn]++;
for(int i=x+1;i<n;i++)
{
if(A[i]>b) now++;
else now–;
C[now+maxn]++;
}
long long ans=0;
now=0;ans+=C[now+maxn];
for(int i=x-1;i>=0;–i)
{
if(A[i]>b) now++;
else now–;
ans+=C[maxn-now];
}
cout<<ans<<endl;
}
P.S最近在做以前浙江省数学竞赛的卷子,突然灵机一动想出了一道编程题,就交到Vijos上面去了。。不知道能不能通过囧。。

SGU 478. Excursion

acm.sgu.ru/problem.php
我更明白了一个事实,就是我是一个沙茶囧。。
这种题目我在当时比赛的时候居然用带上下界的最大流去做。结果悲剧死。。
实际上简单的贪心就可以了。。如果人变多了让boy回来否则让girl出去。。
Code:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<utility>
#define rep(i,n) for(int i=0;i<n;i++)
using namespace std;
typedef pair<int,int> pi;
const int inf=~0U>>1;
int main()
{
freopen("in","r",stdin);
int b,g,n;
cin>>b>>g>>n;
vector<pi> A;
int now=g;
rep(i,n)
{
int x;cin>>x;
if(x>=now)
{
b-=x-now;
if(b<0) break;
A.push_back(pi(x-now,0));
now=x;
}
else
{
g-=now-x;
if(g<0) break;
A.push_back(pi(0,now-x));
now=x;
}
}
if(A.size()<n)
cout<<"ERROR"<<endl;
else
{
rep(i,n)
cout<<A[i].first<<" "<<A[i].second<<endl;
}
}

【VIJOS 1629】 8

www.vijos.cn/Problem_Show.asp
啥也别说了。。直接上容斥原理。。
Code:
#include<iostream>
#define rep(i,n) for(int i=0;i<n;i++)
using namespace std;
const int inf=~0U>>1;
typedef long long ll;
int a,b,A[20],n;
int Count(int a,int b,int x)
{
return b/x-(a-1)/x;
}
ll gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
}
ll lcm(ll a,ll b)
{
return a/gcd(a,b)*b;
}
ll ans=0;int d;
void dfs(int p,ll s,int ch)
{
if(s>b) return;
if(p==n)
{
int d=Count(a,b,s);
if(ch&1) ans-=d;
else ans+=d;
return;
}
ll NewOne=lcm(s,A[p]);
dfs(p+1,NewOne,ch+1);
dfs(p+1,s,ch);
}
void init()
{
cin>>n;
rep(i,n) cin>>A[i];
cin>>a>>b;
}
int main()
{
//freopen("in","r",stdin);
init();
dfs(0,8,0);
cout<<ans<<endl;
}

[VIJOS 1701] Local Maxima

额。。最为VIJOS回归之后做的第一题。还是蛮有意思的。。
传送门
首先可以看出答案是1到n的倒数和。。
有两个办法。。一个是我开始想到的就是设F(x)为1到x的排列的答案。
那么若这个排列第一个是1。那么就是F(x-1)+1否则在中间的1可以忽略掉,就是F(x-1)。。
那么F(x)=( F(x-1)+1 )/x +F(x-1)*(x-1)/x。。
就是F(x)=F(x-1)+1/x。。。
这个方法只有我这样菜的人才想的出来囧。。
一般来说第i个数为Local Maxima的概率就是他为前i个中最大的概率,就是1/i。。
然后+起来。。
不过数据范围太TMD大了。。
我一开始想是不是要用矩阵加速,感觉不是齐次的搞不出来。。。
最后wiki了一下调和数列,发现原来是有公式的。。
zh.wikipedia.org/wiki/%E6%AC%A7%E6%8B%89-%E9%A9%AC%E6%AD%87%E7%BD%97%E5%B0%BC%E5%B8%B8%E6%95%B0
因为精度的问题,对于n<=10^6次方的时候。。暴力计算,
否则使用公式。
Code:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<cmath>
#define rep(i,n) for(int i=0;i<n;i++)
using namespace std;
const int inf=~0U>>1;
const int limit=1e6;
int main()
{
int n;cin>>n;double ans=0;
if(n<=limit)
for(double i=1;i<=n;i++)
ans+=1/i;
else
ans=log((double)n)+0.57721566490153286060651209;
printf("%0.8lfn",ans);
}P.S我的vijos号由于注册的比较早。不叫WJMZBMR。。好像是453844077囧。。我在想是不是为了统一风格就不要原来的号了又舍不得100多道题目囧。。

看Saw有感

      寒假的作业,由于上个学期一直搞OI随笔一篇都没写,作文差了N篇,才补好一篇囧。
这个实际上很早就写了。。但当时太激动,我怕老师觉得我是BT所以改了改囧。

                                    看Saw有感
someone lives without thanksgiving,

but not you ,any more .
    Saw的中文名就是电锯惊魂,说白了就是一部血腥+恐怖片,但我看了之后却觉得,这部片子的导演很伟大,这的的确确是一部反映当前时代精神的片子。

血腥、暴力?嗯,可这在失去灵魂的人面前又算什么?Saw的海报都是一个个失去灵魂的人戴着刑具,脸上除了痛苦什么都没有。实际上这个时代的人的神经已经彻底麻木了,Saw的主角约翰明白还有一种办法可以拯救人,就是痛苦。信仰,宗教,都是虚的,尽管曾经是对的,但是在现在的时代精神面前早已土崩瓦解了,每个人都不再能从他人的脸上看到上帝(哎,我以前是多么相信这个。。),自我的存在意识都逐渐模糊了,人发明了那么多机器,到头来反而被成为机器的机器。
    痛苦?看到他人的痛苦,也感觉到痛苦,内心才能不再麻木?感觉到痛苦,才能感觉到自己原来是存在的?原来不仅仅是视觉+听觉+触觉?不是在看三维电影?还是这个世界中的?

活了几十年的人反而要让别人教他体验到自己的存在,很可笑?很可悲?一点也不,这就是事实。
       Saw里面约翰得了绝症,快死了,他去自杀,没成功,于是决定将余生用来救赎他人的灵魂。折磨他人,让他人对生命感恩。第一部结束的时候,导演还是忍不住插播了画外音,someone lives without thanksgiving, but not you any more..也许是说给经过考验的医生说的,也许是说给观众听的。
       我开始明白为什么有那么多人喜欢自残,那么多人执着于血腥片了,跟爱情和死亡一个道理,想感受到自己存在。

you’re wrong.

No one will change

       但这真的是拯救么,第一部中被约翰救赎的阿凡达在第三部中说you’re wrong , No one will change,也许这本来就是骗人的,约翰只是在报复,报复他没有生命了。约翰之所以是对的是因为他头上有上帝的时钟,一个即将死亡的人?一种宿命感?对他人生命的妒忌?我也不知道是什么。也许就是这样。

TopCoder HigSchool 2010 Round 1

这是第一次比赛。。本来是海选出500个人的。。结果总共都没有500个人囧。。
由于明天就要上学了。。本来不想参加的。。但是根本没有睡意。。于是就上了。。
第一题这个太水了。。怎么做都可以。。

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>

using namespace std;

class TheSequencesLevelOne
{
public:
    vector <int> find(vector <int>);
};

vector <int> TheSequencesLevelOne::find(vector <int> s)
{
    vector<int> ans;
    for(int i=0; i<s.size(); i++)
    {
        int a;
        for(int t=0; t<=7; t++)
        {
            int x=s[i];
            x-=t;
            if(x%4==0||x%7==0)
            {
                a=x;
                break;
            }
            x+=2*t;
            if(x%4==0||x%7==0)
            {
                a=x;
                break;
            }
        }
        ans.push_back(a);
    }
    return ans;
}

//Powered by [KawigiEdit] 2.0!

第二题找规律啊。。奇数位放当前最小的,放了后删掉,偶数位放当前第二小的,放了后删掉,
最后一位特判一下就可以了。。

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>

using namespace std;

class TheSequencesLevelTwo
{
public:
    vector <int> find(vector <int>);
};

vector <int> TheSequencesLevelTwo::find(vector <int> s)
{
    set<int> S(s.begin(),s.end());
    vector<int> Ans;
    for(int i=0; i<s.size()-1; i++)
    {
        if(i%2==0)
        {
            Ans.push_back(*S.begin());
            S.erase(S.begin());
        }
        else
        {
            Ans.push_back(*(++S.begin()));
            S.erase(++S.begin());
        }
    }
    Ans.push_back(*S.begin());
    return Ans;
}

//Powered by [KawigiEdit] 2.0!

第三题的题目可以转化成分成有序的两堆不包括最大数,两堆中相邻元素差不超过K。那么从小到大一个个考虑元素,每个堆有意义的只有大小和最上面的数。。同时一定有一个堆最上面是当前最大的数,所以只要记录3个值就可以了。。然后递推。。算出所有的结果。。然后判断一下最大数就可以了。。
我也不知道为什么我非常WS的用了动态申请。。
dp[i][j][k]当前左边堆有i个,右边堆有j最大的那个在左边堆的最上面,k是右边堆最上面数的编号

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>

using namespace std;

class TheSequencesLevelThree
{
public:
    int find(vector <int>, int);
};
const int mod=1234567891;
int TheSequencesLevelThree::find(vector <int> s, int K)
{
    sort(s.begin(),s.end());
    long long***dp;
    int n=s.size();
    if(n<3) return 0;
    dp=new long long**[n+1];
    for(int i=0; i<=n; i++)
    {
        dp[i]=new long long*[n+1];
        for(int j=0; j<=n; j++)
        {
            dp[i][j]=new long long[n+1];
            for(int k=0; k<=n; k++)
                dp[i][j][k]=0;
        }
    }
    dp[0][0][0]=1;
    int t;
    for(int l=0; l<n; l++)
        for(int i=0; i<=l; i++)
        {
            int j=l-i;
            for(int k=0; k<n; k++)
                if(t=dp[i][j][k])
                {
                    int now=i+j;
                    if(i==0||s[now]-s[now-1]<=K)
                        dp[i+1][j][k]+=t,dp[i+1][j][k]%=mod;
                    if(j==0||s[now]-s[k]<=K)
                        dp[j+1][i][now-1]+=t,dp[j+1][i][now-1]%=mod;
                }
        }
    long long ans=0;
    for(int l=1; l<n-1; l++)
    {
        int r=n-l-1;
        for(int k=0; k<n; k++)
        {
            int x=dp[l][r][k];
            if(s[n-1]-s[k]<=K&&s[n-1]-s[n-2]<=K)
                ans+=x,ans%=mod;
        }
    }
    ans*=2;
    ans%=mod;
    return ans;
}

//Powered by [KawigiEdit] 2.0!

我还Cha掉了一个人的程序。。算法不知道对不对。一看他的特判就知道他判错了。。处女Cha啊。。
我的Coding的速度真是慢死了。。分低的要命。。囧
PS.那个人算法真是对的。。

这么大的随机数据都过了。。反而被我这个Cha掉囧。。

发现一个语法高亮的网站非常NB

我找了N多地方都没有发现什么网站可以高亮scala的。。
后来我看到了一篇文章。找到了这个网站:
www.andre-simon.de/doku/highlight/en/highlight_demo.html
自己看啦,太NB了。。基本可以高清任何代码。。发个效果图
C++:
#include <stdio.h>

int main(void)
{
char msg[13] =
{ 0110, 0145, 0154, 0154, 0157, 054, 040,
0127, 0157, 0162, 0154, 0144, 012 };
int i;

for ( i=0; i<13; i++ )
putchar(msg[i]);

return 0;
}
Java:
public class Fibonacci {
public static long fib(int n) {
if (n <= 1) return n;
else return fib(n-1) + fib(n-2);
}

public static void main(String[] args) {
int N = Integer.parseInt(args[0]);
for (int i = 1; i <= N; i++)
System.out.println(i + ": " + fib(i));
}
}

[HNOI2008]越狱

倒。。这么水的题目都有的。。
Link:61.187.179.132:8080/JudgeOnline/showproblem
正着想有点麻烦。。倒过来想。。
一共有m^n种情况,其中不能越狱的情况中,如果从左往右考虑的话,第一个是m种,其余都是m-1种
所以就是(m-1)^(n-1)*m。。用一个二分计算乘方就可以了。。
减一下就可以了囧。。
Code:

#include<iostream>
using namespace std;
typedef long long ll;
const int mod=100003;
ll m,n;
inline void mul(ll&a,int b){a*=b;a%=mod;}
int power(ll x,int base)
{
if(x==0) return 1;
ll tmp=power(x/2,base);
mul(tmp,tmp);
if(x&1) mul(tmp,base);
return tmp;
}
int main()
{
cin>>m>>n;
int all=power(n,m);
ll sub=power(n-1,m-1);
mul(sub,m);
int ans=all-sub;if(ans<0) ans+=mod;
cout<<ans<<endl;
}
本高亮代码使用codeHl生成,