CodeChef May Challenge 2014

来源:互联网 发布:数据保密协议范本 编辑:程序博客网 时间:2024/05/19 04:25

Chef-jumping

     没什么说的,对6取余,余数0,1,3就yes


Stone
    
      数组初始最大值Max,最小值Min,
                 1)如果k==0
                 2)k%2 ==0 : a[i]-Min
                 3)k%2 ==1 : Max-a[i]


Compilers and parsers
     
    注意只要前缀。


 Chef and Strange Matrix

    对每一行单独考虑,如果修改的数不是在边上,左+右-后,那么他对答案的贡献是0,然后注意不能让i位置的数>i+1的
     
#include<stdio.h>#include<string.h>#include<vector>#include<map>#include<algorithm>using namespace std; vector<int>v[100005];int n,m,p;int x,y;map<int,int>mp;int main(){scanf("%d%d%d",&n,&m,&p);while(p--){scanf("%d%d",&x,&y);v[x].push_back(y);}if(m==1){for(int i=1;i<=n;i++) printf("0\n");return 0;}for(int i=1;i<=n;i++){int s=v[i].size(),tag=1,ans=m-1;sort(v[i].begin(),v[i].end());mp.clear();for(int j=s-1;j>=0;j--){if(v[i][j]==m) ans++;else if(v[i][j]==1) ans--;mp[v[i][j]]++;int x=v[i][j]+1;if(x<=m && x+mp[x]<mp[v[i][j]]+v[i][j]){tag=0;break;}}if(!tag) puts("-1");else printf("%d\n",ans);}return 0;} 


Little Elephant and Balloons

  vector<int>v[i]存第i种颜色的价格,s[i]=v[i].size();
  假设总方案数是num,所有方案的花费和是w,结果就是w/num;
  如何求num, sigma(cnt[i])(i>=m),如何求cnt[i]: sigma(1+((2^s[j])-1)*x)中选幂为i的。。展开就行了
  如何求w,假如我要选i种颜色,并且颜色j必选,那么总的方案数就是way[j]=(sigma(1+((2^s[k])-1)*x)(k!=j)中选幂为i-1的),展开就行了,对于这所求的每一种方案,我们任意加入j颜色的数量都行,如果我们只买j颜色,那么总花费是:买了第k种j颜色,剩下的s[j]-1种j颜色的组合数是 2^(s[j]-1),所以花费是cost[k]=pri[k] * (2^(s[j]-1));也就是说只买j颜色的所有方案的花费和是avg[j] = sigma(cost[k]). 
  综上  sigma(avg[j] * way[j])  / sigma(cnt[i),i>=m);

#include<stdio.h>#include<string.h>#include<vector>#include<stdlib.h>#include<algorithm>using namespace std; inline int input(){int ret=0;char c=getchar();while(c<'0' || c>'9') c=getchar();while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}return ret;} #define clr(a) memset(a,0,sizeof(a))#define rep(i,s,t) for(int i=s;i<t;i++) int t,n,m;int x[50],y[50];int to[50],cnt;double avg[50];double C[50][50];double two[50];double f[50],g[50];vector<int>v[50]; inline void Init(){rep(i,1,41) C[i][0]=C[i][i]=1,C[i][1]=i;rep(i,2,41) rep(j,2,i) C[i][j]=C[i-1][j-1]+C[i-1][j];two[0]=1;rep(i,1,41) two[i]=two[i-1]*2;}int main(){Init();t=input();while(t--){n=input(),m=input();cnt=0;clr(to);rep(i,0,n){x[i]=input(),y[i]=input();if(to[x[i]]==0) to[x[i]]=(++cnt);}rep(i,1,cnt+1) v[i].clear();rep(i,0,n) v[to[x[i]]].push_back(y[i]);rep(i,1,cnt+1){int s=v[i].size();avg[i]=0;rep(j,0,s){avg[i]+=v[i][j]*two[s-1];}}double ans=0;rep(i,m,cnt+1){rep(j,1,cnt+1){clr(f),clr(g),f[0]=1;rep(k,1,cnt+1){if(k==j) continue;int S=v[k].size();rep(r,0,45){g[r]+=f[r];g[r+1]+=f[r]*(two[S]-1);}memcpy(f,g,sizeof(g)),clr(g);}ans+=avg[j]*f[i-1];}}clr(f),clr(g),f[0]=1;rep(i,1,cnt+1){int S=v[i].size();rep(j,0,45){g[j]+=f[j];g[j+1]+=f[j]*(two[S]-1);}memcpy(f,g,sizeof(g)),clr(g);}double num=0;rep(i,m,cnt+1){num+=f[i];}printf("%.8lf\n",ans/num);}return 0;}



Fun with AGp
  
   线段树:对于第一种和第二种操作要分别存一个值,因为((a^b)%p2) %p1!= ((a%p1)^b)%p2%p1;
   操作1: (s+(i-x)*d)*r^(i-x) = ( (s-d*x)*r^i ) / (r^x)  +( d*i*r^i ) / (r^x)  ,如果知道了(r^x)对除数的逆元为ivr,那么也就是 (s-d*x)*ivr *r^i + d*ivr *i *r^i,很显然(s-d*x)*ivr和d*ivr都是定值,就变成简单的区间更新了。但前提是逆元存在,(a/r)%mod,r存在逆元,那么gcd(r.mod)==1,题里面这儿mod是素数,那如果r%mod==0,不能求逆元,那就更简单了,改变的只有一个点了
   操作2,3:略过。

Ps: 因为p1,p2均为素数,所以可以用费马小定理(a^b%mod == (a^(b%(mod-1))) %mod)  减少运行时间。
 
#include <stdio.h>#include <string.h>#include <vector>#include <iostream>#include <stdlib.h>#include <string>#include <math.h>#include <map>#include <algorithm>using namespace std; #define clr(a) memset(a,0,sizeof(a))#define rep(i,s,t) for(int i=s;i<t;i++)#define N 100005#define L (t<<1)#define R (t<<1|1)typedef long long ll; int t,n,q,r,p1,p2,op,s,d,x,y;int a[N];ll ivr1[N],ivr2[N];ll I[N],II[N]; inline ll Pow(ll a,ll b,ll mod){    ll d=1,t=a;    while(b){        if(b&1) d=d*t%mod;        b>>=1;        t=t*t%mod;    }    return d;} struct node{    int lch,rch;    ll sum,A;    ll la,lb,laa,lbb;    ll s1,s2;}root[N<<2]; inline void init(){    clr(ivr1),clr(ivr2);    if(r%p1!=0){    rep(i,1,n+1){    ivr1[i]=Pow(r,i*1LL*(p1-2)%(p1-1),p1);    }    }    if(r%p2!=0){    rep(i,1,n+1){    ivr2[i]=Pow(r,i*1LL*(p2-2)%(p2-1),p2);    }    }    I[0]=II[0]=0;    I[1]=r%p1,II[1]=r%p1;    ll p=r%p1;    rep(i,2,n+1) {    p*=r,p%=p1;    I[i]=I[i-1]+p;    II[i]=II[i-1]+p*i%p1;    I[i]%=p1,II[i]%=p1;    }//sigma(r^i)%p1 and sigma(i*r^i)%p1}  inline void change_sum(int t,ll a,ll b){    root[t].sum += (a*root[t].s1%p1 + b*root[t].s2%p1)%p1;    root[t].sum %= p1;} inline void push_up(int t){root[t].sum = (root[L].sum+root[R].sum)%p1;} inline void change1(int t,ll a,ll b){root[t].la+=a;root[t].la%=p1;root[t].lb+=b;root[t].lb%=p1;change_sum(t,a,b);} inline void change2(int t,ll a,ll b){root[t].laa+=a;root[t].laa%=p2;root[t].lbb+=b;root[t].lbb%=p2;} inline void push_down1(int t){if(root[t].la!=0 || root[t].lb!=0){change1(L,root[t].la,root[t].lb);change1(R,root[t].la,root[t].lb);root[t].la=root[t].lb=0;}} inline void push_down2(int t){if(root[t].laa!=0 || root[t].lbb!=0){change2(L,root[t].laa,root[t].lbb);change2(R,root[t].laa,root[t].lbb);root[t].laa=root[t].lbb=0;}} inline void build(int t,int x,int y){root[t].lch=x,root[t].rch=y;root[t].sum=root[t].A=0;root[t].la=root[t].lb=0;root[t].laa=root[t].lbb=0;root[t].s1=((I[y]-I[x-1])%p1+p1)%p1;root[t].s2=((II[y]-II[x-1])%p1+p1)%p1;if(x==y){root[t].sum=a[x]%p1;root[t].A=a[x]%p2;return;}else{int mid=(x+y)/2;build(L,x,mid),build(R,mid+1,y);push_up(t);}} inline void modefiy(int t,int x,int y,int s,int d,int x1){int lch=root[t].lch,rch=root[t].rch;    if(lch>=x && rch<=y){        ll v1=(((s-d*1LL*x1)%p1+p1)%p1*ivr1[x1]%p1+p1)%p1;        ll v2=d*1LL*ivr1[x1]%p1;        root[t].la+=v1,root[t].la%=p1;        root[t].lb+=v2,root[t].lb%=p1;        change_sum(t,v1,v2);                v1=(((s-d*1LL*x1)%p2+p2)%p2*ivr2[x1]%p2+p2)%p2;       v2=d*1LL*ivr2[x1]%p2;        root[t].laa+=v1,root[t].laa%=p2;        root[t].lbb+=v2,root[t].lbb%=p2;        return;    }    push_down1(t);    push_down2(t);    int mid=(lch+rch)/2;    if(y<=mid) modefiy(L,x,y,s,d,x1);    else if(x>mid) modefiy(R,x,y,s,d,x1);    else{        modefiy(L,x,mid,s,d,x1),modefiy(R,mid+1,y,s,d,x1);    }    push_up(t);} inline void modefiy(int t,int x,int val){int lch=root[t].lch,rch=root[t].rch;if(lch == rch){       ll vv=Pow(r,lch%(p2-1),p2);        root[t].A += (root[t].laa*vv%p2+root[t].lbb*lch%p2*vv%p2)%p2;        root[t].A+=val%p2;root[t].sum+=val%p1;root[t].A%=p2;root[t].sum%=p1;root[t].laa=root[t].lbb=root[t].la=root[t].lb=0;return;}push_down1(t);    push_down2(t);    int mid=(lch+rch)/2;    if(x<=mid) modefiy(L,x,val);    else modefiy(R,x,val);    push_up(t);}   inline void addPow(int t,int x,int val){    int lch=root[t].lch,rch=root[t].rch;    if(lch == rch){        ll vv=Pow(r,lch%(p2-1),p2);        root[t].A += (root[t].laa*vv%p2+root[t].lbb*lch%p2*vv%p2)%p2;        root[t].A %= p2;        root[t].A = Pow(root[t].A,val,p2);        root[t].sum=root[t].A%p1;        root[t].laa=root[t].lbb=root[t].la=root[t].lb=0;        return;    }    push_down1(t);    push_down2(t);    ll mid=(lch+rch)/2;    if(x<=mid) addPow(L,x,val);    else addPow(R,x,val);    push_up(t);} inline ll query(int t,int x,int y){    int lch=root[t].lch,rch=root[t].rch;    if(lch>=x && rch<=y){    return root[t].sum%p1;    }    push_down1(t);    push_down2(t);    int mid=(lch+rch)/2;    if(y<=mid) return query(L,x,y);    else if(x>mid) return query(R,x,y);    else{        return (query(L,x,mid)+query(R,mid+1,y))%p1;    }   } inline int input(){      int ret=0;bool isN=0;char c=getchar();      while(c<'0' || c>'9'){          if(c=='-') isN=1;          c=getchar();      }      while(c>='0' && c<='9'){          ret=ret*10+c-'0';c=getchar();      }      return isN?-ret:ret;  }   int main(){//freopen("in","r",stdin);//freopen("out","w",stdout);t=input();while(t--){n=input(),q=input(),r=input(),p1=input(),p2=input();rep(i,1,n+1) a[i]=input();init();build(1,1,n);while(q--){op=input();if(op==0){s=input();d=input();x=input();y=input();modefiy(1,x,s);if(x+1<=y) modefiy(1,x+1,y,s,d,x);}else if(op==1){x=input(),y=input();addPow(1,x,y);}else{x=input(),y=input();ll ans=query(1,x,y);printf("%lld\n",(ans%p1+p1)%p1);}}}return 0;} 


Sereja and Game

    啊啊啊啊,不会做,赛后看了别人的代码,才知道自己多弱。。。。。对于最积极和随机都用的记忆化搜索,dp[i][g]表示剩余i张牌,gcd是g的概率。

#include <stdio.h>#include <string.h>#include <algorithm>using namespace std; #define clr(a) memset(a,0,sizeof(a))#define rep(i,s,t) for(int i=s;i<t;i++)#define N 110 inline int input(){int ret=0;char c=getchar();while(c<'0' || c>'9') c=getchar();while(c>='0' && c<='9'){ret=ret*10+c-'0';c=getchar();}return ret;} int t,n,a[N],map[N][N];bool vis[N],tag;int win[N][N];double dp[N][N]; inline int gcd(int a,int b){if(!a) return b;if(!b) return a;return gcd(b,a%b);} inline bool dfs1(int cnt,int g){if(win[cnt][g]!=-1) return win[cnt][g];if(cnt==0) return win[cnt][g]=0;int ans=0;rep(i,0,n){if(!vis[i]){int x=map[a[i]][g];if(x!=1){vis[i]=1;if(!dfs1(cnt-1,x)){ans=1;}vis[i]=0;}}if(ans) break;}return win[cnt][g]=ans;} inline double dfs2(int cnt,int g){if(dp[cnt][g]!=-1) return dp[cnt][g];if(cnt==0) return dp[cnt][g]=0;double ans=0;rep(i,0,n){if(!vis[i]){int x=map[a[i]][g];if(x!=1){vis[i]=1;ans+=(1-dfs2(cnt-1,x))/cnt;vis[i]=0;}}}return dp[cnt][g]=ans;} int main(){//freopen("in","r",stdin);//freopen("out","w",stdout);rep(i,0,101) rep(j,0,101) map[i][j]=gcd(i,j);t=input();while(t--){n=input();rep(i,0,n) a[i]=input();rep(i,0,N) rep(j,0,N){dp[i][j]=-1;win[i][j]=-1;}clr(vis);if(dfs1(n,0)==1) printf("1 ");else  printf("0 ");clr(vis);printf("%.4lf\n",dfs2(n,0));}} 


0 0