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
- CodeChef May Challenge 2014
- codechef May challenge A
- codechef May challenge B
- codechef May challenge C
- codechef July Challenge 2014
- codechef December Challenge 2014
- May Challenge 2015(CodeChef 2015年5月月赛)
- Codechef July Challenge 2014部分题解
- codechef August Challenge 2014 第五个题目
- codechef November Challenge 2014 .Chef and Churu
- codechef December Challenge 2012
- codechef December Challenge 2012
- codechef December Challenge 2012
- Codechef February Challenge坑
- CodeChef March Challenge 2015
- Codechef September Challenge 2015
- codechef February Challenge 2016
- Codechef April Challenge 2017
- ViewPager实现QQ主界面,ViewFlipper实现某些新闻应用,自动播放,很流畅
- 1 - BIOS是个什么东东?
- LeetCode Reverse Words in a String
- 数码视讯与新疆广电网络就OTT、金融支付等战略合作
- 图论中的并查集
- CodeChef May Challenge 2014
- Android Launcher 如何实现壁纸居中
- 执行cocos run -p win32命令报error MSB4019:未导入的项目解决方案
- [置顶] 史上最全设计模式导学目录(完整版)
- Android Launcher 如何去掉主菜单,所有应用摆在桌面,类似小米桌面
- 冥想
- mahout itemBase 源码分析
- Restlet 中文版指南
- hdu 2435 dinic算法模板+最小割性质