Time:2018.4.21 8:40-11:40
A
题意
分析
B solved by ym
题意
问平均数为a的n个数,最多有几个数不同
分析
ym:czh赛时清醒的发现可以尽量多的选,而不是直接是一个定值,总和n×a,尽可能多的选那么我们应该怎么选:显然我们想要更多不同的数字,那么我们一定是选择尽可能多的小的 数字,因为用一个大的数字代替几个小的数字会减少小的数的数量,故二分最多可以用多少个小的数,剩下的数用小的数“稀释”,check方法:n-mid>=(n×a-(mid+1)*mid/2)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2e5+7;
long long n,a;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld",&n,&a);
ll l=1,r=n,mid;
while(l<r)
{
mid=(l+r+1)>>1;
if((n*a-mid*(mid+1)/2)>=n-mid)
l=mid;
else
r=mid-1;
}
printf("%lld\n",l);
}
return 0;
}
C solved by ym &czh
题意
问题可以转化为:给一个n,求小于n且与其互质的数(T<=1e5,n<=1e6)
分析)
ym:背锅,想到欧拉函数,但以为是质数= =,欧拉函数:对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目(φ(1)=1 ),显然一个欧拉函数就解决了
D solved by ym
题意
给一个无向图n个点m条边,每条边有一个权值w, 给出K个重要的点,问一个包含全部重要的点的子图的最小值 k (2 ≤ n ≤ 15) () (1 ≤ k ≤ n),
分析
ym:由于n很小,考虑状压dp,知道哪些点已经选,将没有选的点逐渐的添加到已选集合,dp[mask]:从mask状态下出发的最小值
时间复杂度:由于每个点有2^n种状态,O(n*2^n)
#include<bits/stdc++.h>
#define sc scanf
#define pr printf
#define ll long long
using namespace std;
const int maxn = 15+7;
int tot,head[maxn*maxn*2],to[maxn*maxn*2],nxt[maxn*maxn*2],w[maxn*maxn*2];
int t,u,v,c,n,m,k;
int Mask,ans,dp[(1<<16)+7];
void init()
{
Mask=0;
tot=0;
memset(head,0,sizeof(head));
memset(w,0,sizeof(nxt));
memset(nxt,0,sizeof(nxt));
}
void add(int u,int v,int c){
to[++tot]=v;
w[tot]=c;
nxt[tot]=head[u];
head[u]=tot;
}
int maskdp(int x)
{
if(dp[x]!=-1) return dp[x];
if((x&Mask)==Mask) return 0;
dp[x]=1e9;
for(int i=0;i<n;i++)
{
if(((x>>i)&1))
{
for(int j=head[i];j;j=nxt[j])
{
int v=to[j];
if(!((x>>v)&1))
dp[x]=min(dp[x],w[j]+maskdp(x|(1<<v)));
}
}
}
return dp[x];
}
int main()
{
sc("%d", &t);
while(t--){
init();
sc("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++){
sc("%d%d%d", &u,&v,&c);
u--,v--;
add(u,v,c),add(v,u,c);
}
int x;
for(int i=1;i<=k;i++){
sc("%d",&x);
x--;
Mask|=(1<<x);
}
int answer=1e9;
memset(dp,-1,sizeof(dp));
for(int i=0;i<n;i++)
{
answer=min(answer,maskdp(1<<i));
}
pr("%d\n",answer);
}
return 0;
}
E solved by ym
签到
F solved by ym
题意
给出一个n×m的网格,每个格子有一数字num,现有q条询问,每个询问给出询问的网格范围(a<=x<c ,b<=y<=d),问这些网格的median值(median:(2,1,3)==2,(4,2,3,1)==2)
(T<=100,1<=n,m<=100,1<=q<=1e5,1<=num<=500,sum of n×m <= 3×1e5,sum of q<=1e6)
分析
由于num<=500,考虑用二维前缀和记录每个数字出现的频率,对于每次询问,median即为从小到大出现在出现median位置即可
时间复杂度O(T*n*m*num)
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int sum[105][105][505];
int a[105][105];
int now[505];
int t,n,m,q;
int main()
{
scanf("%d",&t);
while(t--){
memset(sum,0,sizeof(sum));
scanf("%d%d%d", &n,&m,&q);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
}
}
// cout<<123<<endl;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int na=a[i][j];
sum[i][j][na]++;
for(int k=1;k<=500;k++)
{
if(i==1){
if(j!=1){
sum[i][j][k]+=sum[i][j-1][k];
}
}
else {
if(j==1){
sum[i][j][k]+=sum[i-1][j][k];
}
else{
sum[i][j][k]=sum[i][j][k]+sum[i][j-1][k]+sum[i-1][j][k]-sum[i-1][j-1][k];
}
}
}
}
}
//cout<<113<<endl;
int x,y,xx,yy;
while(q--)
{
memset(now,0,sizeof(now));
scanf("%d%d%d%d",&x,&y,&xx,&yy);
int allsum=(xx-x+1)*(yy-y+1);
allsum=(allsum+1)/2;
for(int i=1;i<=500;i++)
{
int ans=sum[xx][yy][i]-sum[xx][y-1][i]-sum[x-1][yy][i]+sum[x-1][y-1][i];
allsum-=ans;
if(allsum<=0)
{
printf("%d\n",i);
break;
}
}
}
}
return 0;
}
G
题意
几何
分析
czh来解决一下?
H solve by czh&ym
题意
给出一个字符串 下面给出n次替换,问有多少次替换执行完后,这个字符串成为一个回文串
分析
czh:首先统计有多少个左右不同的字符对,每次更改后,检查更改点字符对的变换,每次执行后如果不同的字符对为0则ans++。我的最大问题在于中点无论怎么变,num都不会改变。需要特判。
I
签到
J solved by ym
题意
给一个区间[L,R],现给出一种切割,一个数可以从中间分成两半(1001???),这个数不含0并且前一半和后一半互质,问区间满足这种切割的最大值
分析
ym:质数间隙了解一下?(暂且可以认为为320),暴力check
K solved by ym
题意
给出ACM比赛的规则,问最后各个奖的归属
分析
ym:所以说写模拟题会送命
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=37;
const int maxm=10000+7;
struct node
{
int p,d,r,o;
friend bool operator < (node a,node b){
return a.o<b.o;
}
}t[maxm];
int tt,n,m,k;
bool v[maxn][maxn];///是否访问过
int f[maxn][maxn]; /// 每个人每个题在答对之间错的次数
int num[maxn]; ///每个队的一血数量
int fb[maxn];
int ans[maxn];
string s;
int hs()
{
int sum=0;
sum=s[0]*100+s[1]*10+s[2]*1;
sum*=60;
sum+=s[4]*10+s[5];
return sum;
}
int main()
{
scanf("%d",&tt);
while(tt--)
{
scanf("%d%d%d", &n, &m,&k);
memset(f,0,sizeof(f));
memset(v,false,sizeof(v));
memset(num,0,sizeof(num));
for(int i=1;i<=k;i++)
{
scanf("%d%d%d",&t[i].p,&t[i].d, &t[i].r);
cin>>s;
t[i].o=hs();
}
for(int i=1;i<=n;i++) fb[i]=-1;
for(int i=1;i<=m;i++) ans[i]=-1;
sort(t+1,t+k+1);
int st=-1,ed=-1,maxdd=0,maxf=0;
for(int i=1;i<=k;i++)
{
int pp=t[i].p, dd=t[i].d, rr=t[i].r;
if(rr==1){
ed=dd;
if(st==-1) st=dd;
if(fb[pp]==-1) fb[pp]=dd;
if(!v[dd][pp])
{
num[dd]++;
maxdd=max(maxdd,num[dd]);
}
ans[dd]=max(ans[dd],f[dd][pp]);
}
else
f[dd][pp]++;
v[dd][pp]=1;
}
for(int i=1;i<=n;i++)
printf("%d%c",fb[i],i==n?'\n':' ');
printf("%d %d ",st,ed);
for(int i=1;i<=m;i++)
if(num[i]==maxdd)
{
printf("%d ",i);break;
}
bool flag=true;
maxf=-5;
for(int j=1;j<=m;j++)
{
maxf=max(maxf,ans[j]);
}
for(int j=1;j<=m;j++)
{
if(ans[j]==maxf)
{
cout<<j<<endl;
break;
}
}
}
return 0;
}
Summary
Ym:菜菜啊,K题过的人好多,大家都会大模拟呀,这个水平去reginoal药丸,大力切题呀
Czh: