20190825

纵饮孤独 提交于 2019-11-28 14:50:50

期望: 60 + 30 + 20 = 110.实际: 40 + 0 + 10 = 50.

T1:给定一个正整数 M ,找出有多少不同的正整数对 (x, y) 使得存在正整数 p 和 q,满足下面这个方程:p*x2 + q*y = M.

S1:开局以为是数学题,套某个定理,想不到打了暴力,不知到>500的点为什么错了.后面跟dalao讨论,发现枚举的顺序有问题,导致TLE与WA.对于60pts,正确的打开方式应该为先枚举x( x<=sqrt ( m ) ),再枚举y( y<=m ),再枚举p.(p*x*x<m),一旦枚举到p,使x,y成立,就break.看上去o(n^3),其实为o(能过60pts).正解其实为暴力的优化,我们将p放在第二维枚举,第三维不枚举j,直接枚举m-x*x*p的因子,合法的y一定在其中,这样o(能过100pts)就解决了.

#include<iostream>  #include<cstring>  #include<cstdio>  #include<vector>  using namespace std;  #define re register  int T,m,ans,vis[200010];  vector<int> v[200010];  inline int fd(){      int s=1,t=0;      char c=getchar();      while(c<'0'||c>'9'){          if(c=='-')              s=-1;          c=getchar();      }      while(c>='0'&&c<='9'){          t=t*10+c-'0';          c=getchar();      }      return s*t;  }  void work()  {      for(re int i=1;i<=200000;++i)          for(re int j=1;j*i<=200000;++j)              v[i*j].push_back(i);  }  int main()  {      freopen("pairs.in","r",stdin);      freopen("pairs.out","w",stdout);      T=fd(),work();      while(T--){          m=fd();          ans=0;          for(re int x=1;x*x<=m;++x){              for(re int p=1;p*x*x<m;++p){                  int cnt=v[m-x*x*p].size();                  for(re int k=0;k<cnt;++k)                      if(!vis[v[m-x*x*p][k]]){                          ++ans;                          vis[v[m-x*x*p][k]]=1;                      }              }              for(re int p=1;p*x*x<m;++p){                  int cnt=v[m-x*x*p].size();                  for(re int k=0;k<cnt;++k)                      vis[v[m-x*x*p][k]]=0;              }          }          printf("%d\n",ans);      }      return 0;  }

T2:幼儿园老师正在给小朋友们排座位.一共有 N 个小朋友, M 个座位.为了尽量让小朋友分到自己喜欢的座位上去,决定让每个小朋友都选出两个自己最想坐的位置.小朋友们选好之后,老师却犯愁了.老师现在想知道,一共有多少种安排座位的方式能满足所有小朋友的意愿?由于答案可能很大,你需要将其对 10000019 取模后输出.

S2:显然30pts用于dfs,但是题目说明了小朋友选的两个座位可能是一样的,选择这两个座位的方案只算一种,在dfs要判重(30pts - > 0 pts).正解:考虑将座位看成点,小朋友喜欢的两个座位连一条双向边.我们要做的是将边定向.规定a-->b为选b,b-->a为选a.在一个n个点,m条边的联通块内,考虑以下几种情况:①:n<m,座位小于人数,显然无解.②:n-1==m.将每一个点做为根,都会使每一条边得到唯一方向,所以有n种方案.③:n==m,无自环.显然顺逆时针,两种方案.④:n==m,有自环,自环的两点选择唯一确定,全局方案唯一.最后利用乘法原理,将每个连通块的方案相乘即为ans.

#include<iostream>  #include<cstring>  #include<cstdio>  using namespace std;  #define re register  const int mod=10000019;  const int maxn=200010*10+10;  int T,n,m,cnt,ans,vis[maxn],sum[maxn],head[maxn];  struct bian{      int next,to;  }len[maxn<<1];  inline int fd(){      int s=1,t=0;      char c=getchar();      while(c<'0'||c>'9'){          if(c=='-')              s=-1;          c=getchar();      }      while(c>='0'&&c<='9'){          t=t*10+c-'0';          c=getchar();      }      return s*t;  }  void add(int from,int to){      len[++cnt].to=to;      len[cnt].next=head[from];      head[from]=cnt;  }  void dfs(int x,int &n,int &m,int &flag){      if(vis[x]) return;      vis[x]=1;      ++n,m+=sum[x];      for(re int k=head[x];k;k=len[k].next){          int to=len[k].to;          if(to==x) flag=1;          dfs(to,n,m,flag);      }  }  int work(int x){      int n=0,m=0,flag=0;      dfs(x,n,m,flag);      m/=2;      if(m>n) return 0;      if(flag) return 1;      if(n==m) return 2;      return n;   }  int main()  {      freopen("seat.in","r",stdin);      freopen("seat.out","w",stdout);      T=fd();      while(T--){          n=fd(),m=fd();          memset(head,0,sizeof(head));          memset(vis,0,sizeof(vis));          memset(sum,0,sizeof(sum));          for(re int i=1;i<=n;++i){              int from=fd(),to=fd();              add(from,to),add(to,from);              ++sum[from],++sum[to];          }          ans=1;          for(re int i=1;i<=m;++i)              if(!vis[i])                  ans=1ll*ans*work(i)%mod;          printf("%d\n",ans);      }      return 0;  }

T3:给定一个整数 N ,请你计算 (7 +4√3 ) N 的整数部分模 1000000007 后的结果.

 

#include<iostream>  #include<cstring>  #include<cstdio>  using namespace std;  #define e exit(0)  #define re register  const int mod=1000000007;  int T,n,ans;  inline int fd(){      int s=1,t=0;      char c=getchar();      while(c<'0'||c>'9'){          if(c=='-')              s=-1;          c=getchar();      }      while(c>='0'&&c<='9'){          t=t*10+c-'0';          c=getchar();      }      return s*t;  }  struct jz{      int a[5][5];      jz(){memset(a,0,sizeof(a));}      jz operator*(const jz &p){          jz ans;          for(re int k=1;k<=2;++k)              for(re int i=1;i<=2;++i)                  for(re int j=1;j<=2;++j)                      ans.a[i][j]=(ans.a[i][j]%mod+1ll*a[i][k]*p.a[k][j]%mod)%mod;          return ans;      }  };  jz work(){      jz g;      g.a[1][1]=7,g.a[1][2]=4;      g.a[2][1]=12,g.a[2][2]=7;      return g;  }  jz qsm(jz k,int y){      jz ans;      for(re int i=1;i<=2;++i)          ans.a[i][i]=1;      while(y){          if(y&1) ans=ans*k;          k=k*k;          y>>=1;      }      return ans;  }  int main()  {      freopen("math.in","r",stdin);      freopen("math.out","w",stdout);      T=fd();      while(T--){              n=fd();          if(n==0){              printf("1\n");              continue;          }          else if(n==1){              printf("13\n");              continue;          }          jz k=work();          k=qsm(k,n-1);          ans=(1ll*7*k.a[1][1]%mod+1ll*4*k.a[2][1]%mod)%mod;          ans=(1ll*2*ans%mod-1%mod)%mod;          printf("%d\n",ans);      }      return 0;  }

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!