HDU4646_Laser Beam

题目是这样的,一个等边三角形,三边都是有镜子组成的。

现在要你从一个点射入一条光线,问你如果要求光线在三角形里面反射n次然后从入点射出来的话,入射的方向可能有多少种?

这。。。。。其实不难。关键是要搞清楚镜子反射的规律。

这样来理解。反射的话相当于在另一面也是一个三角形,这样我们可以把同样的等腰三角形铺满整个二维空间。

这样就会发现规律,如果我们把所有的点都分层,那么发现射到第一层的反射次数为1,第二层为3,第三才层为5,这样下来我们就可以知道如果要反射n次射出的那个对称点应该在那个层数了。

到此我们唯一的问题就是求出每一层有多少个点了。

但是有多少个点就是答案吗?  不是的,如果后面的点被前面的点遮挡了,那么那个点是不算的。

嗯大概就是这样。 基本的解法就是这样的了。。。  只是个人想法。求指教。

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#define ll long long
using namespace std;

ll t,n;
map<ll,ll> g;

ll f(ll x)
{
    if (x%2==0) return 2*(x/6+1)-1;
        else return 2*((x-3)/6+1);
}

ll get(ll x)
{
    if (g[x]!=0) return g[x];
    g[x]=f(x);
    for (ll i=2; i*i<=x; i++)
    {
        if (x%i>0) continue;
        g[x]-=get(i);
        if (i*i!=x)
        {
            g[x]-=get(x/i);
        }
    }
    return g[x];
}

int main()
{
    scanf("%I64d",&t);
    while (t--)
    {
        scanf("%I64d",&n);
        if (n%3==0)
        {
            printf("0\n");
            continue;
        }
        if ((n&1)==0)
        {
            printf("0\n");
            continue;
        }
        if (n==1)
        {
            printf("1\n");
            continue;
        }
        if (n==3)
        {
            printf("0\n");
            continue;
        }
        n=(n+3)>>1;
        printf("%I64d\n",get(n));
    }
    return 0;
}

 

posted @ 2013-11-19 21:24  092000  阅读(497)  评论(0编辑  收藏  举报