2012金华网络赛

A very hard Aoshu problem

这个题敲一个dfs就可以AC了,注意等号左边dfs的时候hash一下,右边取hash的值加起来。然后枚举等号的位置就好了。

#include <cstdio>
#include <string.h>
#include <map>
using namespace std;
typedef long long ll;
map <ll,int> hash;
ll tot;
char s[100];
int dfs(int l, int r, ll pre, ll sum, int mode)
{
    if (l>r)
    {
        if (pre==0){
            if (mode==0){
                hash[sum]++;
                //printf("sum=%d\n",sum);
            }
            else{
                tot+=hash[sum];
            }
        }
        return sum;
    }
    dfs(l+1,r,0,sum+pre*10+s[l]-'0',mode);
    dfs(l+1,r,pre*10+s[l]-'0',sum,mode);
    return sum;
}
int main()
{
    int i,j,k;
    while ( scanf("%s",s), *s!='E' )
    {
        tot=0;
        for (i=0; i<strlen(s)-1; i++){
            hash.clear();
            dfs(0,i,0,0,0);
            dfs(i+1,strlen(s)-1,0,0,1);
        }
        printf("%I64d\n",tot);
    }


    return 0;
}


 

Aeroplane chess

 期望DP,要记住每个点到达的概率,步数等状态,直接飞走的点另外考虑。
另外,正着推和反着推不太一样,可以先在纸上模拟一下,感觉过样例一般都能AC

 

#include <stdio.h>
#include <string.h>
#define NN 102100
const double p=1.0/6.0;
double dp[NN][2];
int  n,m,x,y;
int to[NN],from[NN];
int flight(int k){
    if (to[k]==-1) return k;
    int tmp=flight(to[k]);
    to[k]=tmp;
    return tmp;
}
void Readln(){
        memset(dp,0,sizeof(dp));
        memset(to,-1,sizeof(to));
        memset(from,-1,sizeof(from));
        for (int i=0; i<m; i++)
        {
            scanf("%d %d",&x,&y);
            to[x]=y;
            from[y]=x;
        }

        for (int i=0; i<=n; i++)
            flight(i);
}
int main(){
    int i,j,k;
    while ( scanf("%d %d",&n,&m),!(m==0 && n==0) )
    {
        Readln();
        dp[0][0]=0;
        dp[0][1]=1;
        for (i=0; i<n; i++ )
        {
            if (to[i]!=-1) continue;
            if (dp[i][1]<1e-8) continue;
            dp[i][0]=dp[i][0]/dp[i][1];
         //   dp[i][1]=1;
            for (j=1; j<=6 ; j++)
            {
                int k;
                k=flight(i+j);
                dp[k][0]+=( (dp[i][0]+1) /6.0 * dp[i][1]);
                dp[k][1]+=dp[i][1]*p;
            }
//            printf("grid=%d exp=%.4f  gailv=%.4f\n",i,dp[i][0],dp[i][1]);
        }
        double sum=0;
        double sp=0;
        for (i=n;i<n+6;i++) {
//            sum+=dp[i][0];
            sum+=dp[i][0];
            sp +=dp[i][1];
//            printf("%.4f\n",dp[i][0]);
        }

        printf("%.4f\n",sum/sp);

/*        for (i=0; i<=n; i++){
            printf("%d to    %d\n",i,to[i]);
            printf("%d from  %d\n",from[i],i);
        }*/

    }


    return 0;
}


Sum

这题用容斥来做,p分解质因数,得到q[],凡是q[]的倍数都不与p互质,用容斥算算吧
c那个操作不多,可以把c通通记下来,询问的时候再修正。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <map>
#include <cmath>
using namespace std;
#define NN 651000
typedef __int64 LL;
map < LL , LL > op;
map < LL , LL >::iterator it;
LL n,m;
LL gcd(LL a,LL b){ return b?gcd(b,a%b):a;}
LL sum[NN];
/*
LL getsum(LL x, LL y, LL p){
    LL ret=0;
    for (LL i=x; i<=y; i++)
    {
        if ( gcd(i,p)==1 ) ret+=i;
    }
    return ret;
}
*/
LL dfs(LL k, LL deep, LL *p, LL n, LL y, LL mul)
{
    if (deep==0)
    {
        LL count=y/mul;
//        printf("mul=%lld\n",count*(count+1)*mul/2);
        return (count*(count+1)*mul/LL(2));
    }
    LL sum=0;
    for (LL i=k; i<n; i++)
    {
        mul*=p[i];
        sum+=dfs(i+1,deep-1,p,n,y,mul);
        mul/=p[i];
    }
    return sum;
}
LL gets(LL n,LL *p)//[1,n] p
{
    if (n==1) return 1;
    if (n<1)  return 0;
    LL ret=0,sg=1;
    for (LL i=1;i<=p[0];i++)
    {
        ret+=sg*dfs(0,i,p+1,p[0],n,1);
        sg=sg*(-1);
//        printf("i=%d ret=%lld\n",i,ret);
    }
    return (sum[n]-ret);
}

LL getsum(LL x, LL y, LL px)
{
    LL count=0,i=2;
    LL p[50];
    LL sp=sqrt(px+0.0);
    while (px>1)
    {
        if (px%i == 0)
        {
            while (px%i == 0) px/=i;
            p[++count]=i;
        }
        i++;
        if (i>sp) i=px;
    }
    p[0]=count;
    LL ret;
    ret=gets(y,p)-gets(x-1,p);
//    for (LL i=1; i<=count; i++) printf("p[%d] = %d\n",i,p[i]);
    return ret;
}

LL Query(LL x, LL y, LL p){
    LL ret=0;
    LL tmp=getsum(x,y,p);
    ret=tmp;
//    if (p==1) ret = (sum[y]-sum[x-1]);
    for (it=op.begin();it!=op.end();it++)
    {
        LL x1,c1;
        x1=it->first;
        c1=it->second;
        if (x1>=x&&x1<=y)
        {
            if ( gcd(x1,p)==1 ) ret-=x1;
            if ( gcd(c1,p)==1 ) ret+=c1;
        }
    }
    return ret;
}
void init(){
    sum[0] = 0;
    for(LL i = 1; i < NN; i++)
        sum[i] = sum[i-1] + i;
}
void fun(){

    LL i,j,k;
        op.clear();
        LL ch,x,y,p;
        scanf("%I64d %I64d",&n,&m);
        for (i=0; i<m; i++)
        {
            scanf("%I64d",&ch);
            if (ch==1)
            {
                scanf("%I64d %I64d %I64d",&x,&y,&p);
                printf("%I64d\n" ,Query(x,y,p) );
            }
            else
            {
                scanf("%I64d %I64d",&x,&y);
                op[x]=y;
            }
        }
}
int main(){
    init();
    LL T;
 /*   LL p[30];
    p[0]=2;p[1]=3;p[2]=2;
    printf("%I64d\n",getsum(1,3,6));
    return 0;*/

    scanf("%I64d",&T);
    while (T--)
    {
        fun();

    }

    return 0;
}


 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值