一次不知道该叫什么的模拟赛和一篇不知道该起什么标题的补题

来源:互联网 发布:外国人代购淘宝 编辑:程序博客网 时间:2024/05/01 09:51

这套题前部分略水,但T2的正解(虽然A了),T5的优化,以及T6,在下都束手无策,还需要好好学习啊。。。。自己还是太水了。。。。

A题

模拟。。。直接贴代码了。。。、

#include<iostream>#include<string.h>#include<math.h>#include<stdio.h>#include<algorithm>using namespace std;int n;string h;int a[30],cnt=0;int main(){freopen("trener.in","r",stdin);freopen("trener.out","w",stdout);cin>>n;getchar();for(int i=1;i<=n;i++)cin>>h,a[h[0]-'a']++;for(int i=0;i<=25;i++)if(a[i]>=5)cout<<(char)(i+'a'),cnt++;if(cnt==0)cout<<"PREDAJA";}

B题

n个人分m个蛋糕,求最小切刀数

啊啊啊其实正解很简单啊,从头到尾一个个模拟就好了,然而人比较笨虽然A了但就是死活想不到

        cin>>n>>m;for(int i=0;i<=n*m;i+=n) if(i%m!=0) ans++;cout<<ans<<endl;

本人做法挺离谱的,有递归做solve(n,m),n->当前剩的面包,m->要分的人

当n>=m时,说明每人吃超过1块面包,n=n%m;

当m>n时,处理此时应该把每个面包分成多少份x,和给每个人应发多少份y,先给x/y *n个人分够他们的量,那么m=m-x/y*n,同时ans+=x/y*n;

如果n=0,说明没有面包再分了,没必要做了,直接return;

如果m=0,说明没有人必要分了,但我还保留了这n块“空面包”,它们实际没必要被切,那么ans-=n;

是不是很严(fu)谨(za)啊。。。

#include<iostream>#include<math.h>#include<string.h>#include<stdio.h>#include<algorithm>using namespace std;int gcd(int a,int b){if(b==0)return a;return gcd(b,a%b);}int lcm(int a,int b){return a*b/gcd(max(a,b),min(a,b));}int ans,n,m,gong,mei,qie;void jie(int n1,int m1){if(n1==0)return ;if(m1==0){ans-=n1;return ;}if(n1>=m1){int gong=lcm(n1,m1),qie=gong/n1,mei=gong/m1;int zhi=(mei/qie)*m1,yu=n1-zhi;jie(yu,m1);}else{int gong=lcm(n1,m1),qie=gong/n1,mei=gong/m1;ans+=qie/mei*n1;jie(n1,m1-qie/mei*n1);}}int main(){freopen("kusac.in","r",stdin);freopen("kusac.out","w",stdout);scanf("%d%d",&n,&m);jie(n,m);cout<<ans;}

C题

给出一幅N*N的地图,每个格子上都有一个权值,求出有多少对矩形“对角”(即只有一个公共点)而且权值和相等。

先做一遍前缀和sum[i][j]表示从(1,1)到(i,j),那么我们就可以通过O(4)的复杂度求出任意一个矩形内的权值和。

枚举点(i,j)的右下点作为“对点”,先从(1,1)到(i,j)把所有以此为右下角的矩形都枚举一边,并把它们在对应值数组里个数+1,然后再枚举以这个点作为左上角的矩形们,并答案+=它在对应数组里的值,及这个值在左上方矩形(即以(i,j)为右下角的顶点的矩形们)出现过的次数,对与以(i,j)右上角,左下角的矩形做法也是同理。

注意在清空访问值次数时,不能直接memset,会很慢,应该在更新值出现次数时记录一下,最后清零时直接访问改即可。

#include<iostream>#include<string.h>#include<math.h>#include<stdio.h>#include<algorithm>using namespace std;int map[55][55],sum[55][55];int in[5000050];int g[2700];int getsum(int x1,int y11,int x2,int y2){return sum[x2][y2]-sum[x2][y11-1]-sum[x1-1][y2]+sum[x1-1][y11-1];}int ans=0,n,gh[2555];int main(){freopen("ratar.in","r",stdin);freopen("ratar.out","w",stdout); scanf("%d",&n);for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%d",&map[i][j]),sum[i][j]=map[i][j];for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)sum[i][j]+=sum[i-1][j];for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)sum[i][j]+=sum[i][j-1];for(int i=1;i<n;i++){for(int j=1;j<n;j++){int f,cnt=0;for(int i1=1;i1<=i;i1++)for(int j1=1;j1<=j;j1++)f=getsum(i1,j1,i,j)+2500000,in[f]++,gh[++cnt]=f;for(int i1=i+1;i1<=n;i1++)for(int j1=j+1;j1<=n;j1++)ans+=in[getsum(i+1,j+1,i1,j1)+2500000];for(int i1=1;i1<=cnt;i1++)in[gh[i1]]=0;cnt=0;for(int i1=i+1;i1<=n;i1++)for(int j1=1;j1<=j;j1++)f=getsum(i+1,j1,i1,j)+2500000,in[f]++,gh[++cnt]=f;for(int i1=1;i1<=i;i1++)for(int j1=j+1;j1<=n;j1++)ans+=in[getsum(i1,j+1,i,j1)+2500000];for(int i1=1;i1<=cnt;i1++)in[gh[i1]]=0;}}cout<<ans<<endl;}


D题

一个很蠢的贼(而且还是被政府雇佣的。。。),他带了一堆包,都有容量,还有一堆珠宝,每个珠宝都有一定体积和一定价值,然而!!他只打算在每个包里只装一个珠宝。。。于是这道题从一个很好的背包问题变成了一个很蠢的贪心。。。

以一个结构体,存入所有的珠宝和背包,背包的价值设为-1以区别。按照容量按照小值sort一下,如果价值不为-1那么把这个值push进优先队列(最大值优先)里,如果是-1,

如果队列不为空,ans+=队首,并且将其出队。

#include<iostream>#include<string.h>#include<algorithm>#include<stdio.h>#include<math.h>#include<queue>#include<vector>using namespace std;priority_queue<int> q;struct ba{int v,room;}bag[600500];int cmp(ba a,ba b){return (a.room==b.room)?a.v>b.v:a.room<b.room;}int n,m;long long ans;int main(){freopen("lopov.in","r",stdin);freopen("lopov.out","w",stdout);scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d%d",&bag[i].room,&bag[i].v);for(int i=1;i<=m;i++)scanf("%d",&bag[i+n].room),bag[i+n].v=-1;sort(bag+1,bag+m+n+1,cmp);for(int i=1;i<=n+m;i++){if(bag[i].v!=-1)q.push(bag[i].v);elseif(!q.empty())ans+=q.top(),q.pop();}cout<<ans<<endl;}

E题

给出一堆数,请计算i*(因数中含有I的数的个数)

我写的是裸的(做法是那种一读题就懂的),然而T了1个点。。。。

void init(){for(int i=2;i<=2000000;i++){if(prim[i]==0)for(int j=1;i*j<=2000000;j++)if(prim[i*j]==0) prim[i*j]=i;}}void get(int x){    size=1;tmp[0]=1;    while(x>1){        int p=prim[x];        int pow=1;        for(;x>1&&prim[x]==p;x/=p) pow++;        for(int i=size;i<size*pow;i++) tmp[i]=tmp[i-size]*p;        size*=pow;    }   }

加了马大佬的这个优化,就能过了。

他的这个算法复杂度小于o(根号n),思路是用prim[i]存i的第一个质因数,然后一直分解到j并将所有j的i倍数(得小于等于它含i的个数)一解决,紧接着再递归处理,并把他们的i倍加进去就好了。

F题

后缀数组还不会,题解也看不太懂。。明天继续连载。。。

0 0