首页 > 代码库 > 2014多校联合第一场
2014多校联合第一场
1001:Couple doubi
暴力打表找规律可知,对于任意的p。
(1^i+2^i+...+(p-1)^i)%p={
非0 ,i%(p-1)==0
0 , i%(p-1)!=0
}
所以,结果就很显然了。
#include <iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<stdlib.h> #include<cmath> using namespace std; #define eps 1e-4 #define zero(x) ((fabs(x)<eps)?0:x) int main() { int n,k; while(~scanf("%d%d",&n,&k)) { int x=n/(k-1); if(x%2==0)cout<<"NO"<<endl; else cout<<"YES"<<endl; } return 0; }
1004:Task
很显然,y对总值的影响远小于x。
所以:
按y排序,y小的放在前面,然后按x排序,x小的放在前面,然后按属性排序,任务放在前面。
然后依次遍历这些点。
如果当前点为任务:
把当前任务的价值放入set中。
如果当前点为机器:
在set中寻找最后一个比当前机器的价值小的任务。
#include <iostream> #include<stdio.h> #include<set> #include<vector> #include<algorithm> using namespace std; #define LL long long struct list { int x; int y; int s; int leap; friend bool operator <(const list &a,const list &b) { if(a.y!=b.y)return a.y<b.y; else if(a.x!=b.x)return a.x<b.x; else return a.leap<b.leap; } }node[220000]; multiset<int>st; multiset<int>::iterator it; int sea(int x) { if(st.size()==0)return 0; it=st.begin(); if(x<(*it))return 0; it=st.lower_bound(x); if(it==st.end()) { it=st.end(); it--; int ans=(*it); st.erase(it); return ans; } if((*it)==x) { st.erase(it); return x; } it--; int ans=(*it); st.erase(it); return ans; } void dos(int n) { int x=0; LL sum=0; st.clear(); for(int i=1;i<=n;i++) { if(node[i].leap==1) { int res=sea(node[i].s); if(res) { x++; sum+=(LL)res; } } else { st.insert(node[i].s); } } cout<<x<<" "<<sum<<endl; } int main() { int n,m; while(~scanf("%d%d",&n,&m)) { for(int i=1;i<=n;i++) { scanf("%d%d",&node[i].x,&node[i].y); node[i].leap=1; node[i].s=node[i].x*500+node[i].y*2; } for(int i=n+1;i<=n+m;i++) { scanf("%d%d",&node[i].x,&node[i].y); node[i].leap=0; node[i].s=node[i].x*500+node[i].y*2; } sort(node+1,node+n+m+1); for(int i=1;i<=n+m;i++) { //cout<<node[i].x<<" "<<node[i].y<<" "<<node[i].leap<<endl; } dos(n+m); } return 0; }
1005:Peter‘s Hobby
wh[i][j]:天气为i,叶子的状态为j的概率。
ww[i][j]:今天天气为i,明天天气为j的概率。
st[i]:第一天天气为i的概率。
叶子的状态序列为{b1,b2...bn}
那么对于某个天气序列{a1,a2....an}的概率为:
st[a1]*wh[a1][b1]* ww[a1][a2] *wh[a2][b2]* ww[a2][a3]* wh[a3][b3]*........*ww[an-1][an]*wh[an][bn];
因为结果有可能很小,所以用log把乘法转化为加法。
然后就是很明显的dp求路径了。。。。
#include <iostream> #include<stdio.h> #include<set> #include<vector> #include<math.h> #include<algorithm> #include<string.h> using namespace std; #define LL long long #define INF 99999999 #define eps 1e-6 #define zero(x) ((fabs(x)<eps)?0:x) double wh[3][4]={ {0.6,0.2,0.15,0.05}, {0.25,0.3,0.2,0.25}, {0.05,0.10,0.35,0.5} }; double ww[3][3]={ {0.5,0.375,0.125}, {0.25,0.125,0.625}, {0.25,0.375,0.375} }; double st[3]={0.63,0.17,0.2}; double dp[55][3]; double ans[55][3]; vector<int>vec; int a[110]; char str[110]; void dfs(int x,int y) { //cout<<y<<endl; vec.push_back(y); if(x==1) { return ; } for(int i=2;i>=0;i--) { if(zero(ans[x][y]-(ans[x-1][i]+dp[x][y]+ww[i][y]))==0) { dfs(x-1,i); break; } } } int main() { int T,cas,n; scanf("%d",&T); cas=0; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { ww[i][j]=log(ww[i][j]); } } while(T--) { vec.clear(); cas++; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s",str); int x=strlen(str); if(x==3)a[i]=0; else if(x==6)a[i]=1; else if(x==4)a[i]=2; else if(x==5)a[i]=3; } memset(dp,0,sizeof(dp)); double s=0; for(int i=1;i<=n;i++) { s=0; for(int j=0;j<3;j++) { dp[i][j]=wh[j][a[i]]; s+=dp[i][j]; } for(int j=0;j<3;j++)dp[i][j]=dp[i][j]/s; } for(int i=1;i<=n;i++) { for(int j=0;j<3;j++) { dp[i][j]=log(dp[i][j]); } } for(int i=1;i<=n;i++) { for(int j=0;j<3;j++)ans[i][j]=-INF; } for(int j=0;j<3;j++) { ans[1][j]=dp[1][j]+log(st[j]); } for(int i=2;i<=n;i++) { for(int j=0;j<3;j++) { for(int k=0;k<3;k++) { double ps=ans[i-1][k]+ww[k][j]+dp[i][j]; ans[i][j]=max(ans[i][j],ps); } } } for(int i=1;i<=n;i++) { for(int j=0;j<3;j++) { // cout<<ans[i][j]<<" "; } // cout<<endl; } double maxx=-INF; int p=0; for(int j=0;j<3;j++) { if(maxx<ans[n][j]) { maxx=ans[n][j]; p=j; // cout<<maxx<<" "<<p<<endl; } } dfs(n,p); printf("Case #%d:\n",cas); for(int i=n-1;i>=0;i--) { if(vec[i]==0)puts("Sunny"); if(vec[i]==1)puts("Cloudy"); if(vec[i]==2)puts("Rainy"); } } return 0; }1009:Turn the pokers
假如初始全部是正面(状态为0)。
全部操作完成后,正面的个数为x个。
那么x有很多种情况。假如分别为{x1,x2....xk}
那么结果为C(m,x1)+C(m,x2)+C(m,x3)+...+C(m,xk).
很明显可以得知x1,x2...xk奇偶性一致。
我们试验几组例子可知,x1,x2...xk是一段连续的区间。
那么我们只需要求出x1,xk就可以了。
然后我们就可以每走一步,根据上一步的x1,xk,确定这一步之后的x1,xk.
#include <iostream> #include<cmath> #include<algorithm> #include<cstdio> using namespace std; #define LL long long #define mod 1000000009 LL jie[110000]; void init() { jie[0]=1; jie[1]=1; for(int i=2;i<=100000;i++) { jie[i]=jie[i-1]*i; jie[i]=jie[i]%mod; } } LL qmod(LL x,LL y) { if(y==0)return 1; if(y==1)return x%mod; LL ans=qmod(x,y/2); ans=(ans*ans)%mod; if(y%2)ans=(ans*x)%mod; return ans; } LL dos(int n,int m) { LL ans=jie[n]; ans=(ans*qmod((jie[m]*jie[n-m])%mod,mod-2))%mod; return ans; } int main() { init(); int n,m,x; while(~scanf("%d%d",&n,&m)) { int l,r; scanf("%d",&x); l=r=x; int ll,rr; for(int i=2;i<=n;i++) { scanf("%d",&x); ll=l-x; rr=r+x; if(ll<0) { if(r-x<0)ll=0+x-r; else ll=((l-x)%2+2)%2; } if(rr>m) { if(l+x<=m)rr=m-(r+x)%2; else rr=m-(l+x-m); } l=ll; r=rr; } LL ans=0; for(int i=l;i<=r;i+=2) { ans+=dos(m,i); ans=ans%mod; } cout<<ans<<endl; } return 0; }