A. Grandma Laura and Apples
题意:n个人买苹果,每个人当前买一半的苹果,每个苹果p(偶数)元,输入half代表当前有偶数个苹果;halfplus代表当前有奇数个苹果,
因为是奇数,所以多的0.5个苹果送给这个人。
分析:逆着算钱,第i次的钱是i+1的两倍,如果是halfplus就加p/2。ans加上这次的钱就好了。
代码:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<queue> #include<cmath> #include<stack> #include<set> #include<map> #define INF 0x3f3f3f3f #define Mn 50 #define Mm 2000005 #define mod 1000000007 #define CLR(a,b) memset((a),(b),sizeof((a))) #define CPY(a,b) memcpy ((a), (b), sizeof((a))) #pragma comment(linker, "/STACK:102400000,102400000") #define ul u<<1 #define ur (u<<1)|1 using namespace std; typedef long long ll; int a[Mn]; int main() { int n,m; string s; scanf("%d%d",&n,&m); ll ans=0,b=0; for(int i=1;i<=n;i++) { cin>>s; if(s[s.size()-1]=='s') { a[i]=1; } else { a[i]=0; } } for(int i=n;i>=1;i--) { b=b*2; if(a[i]==1) b+=m/2; ans+=b; } cout<<ans<<endl;; return 0; }
B. Alice, Bob, Two Teams
题意:给一个长度为n的数组p和串s,表示有p[i]个s[i],s串只包含‘A’,‘B’。有唯一一次操作,让串前缀或后缀全部反转(A->B,B->A),问B最多为多少。
分析:前后维护前缀和就好了。
代码:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<queue> #include<cmath> #include<stack> #include<set> #include<map> #define INF 0x3f3f3f3f #define Mn 2000010 #define Mm 2000005 #define mod 1000000007 #define CLR(a,b) memset((a),(b),sizeof((a))) #define CPY(a,b) memcpy ((a), (b), sizeof((a))) #pragma comment(linker, "/STACK:102400000,102400000") #define ul u<<1 #define ur (u<<1)|1 using namespace std; typedef long long ll; ll q[Mn],a[Mn],b[Mn]; char s[Mn]; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%I64d",&q[i]); } scanf("%s",s+1); ll ans=0; for(int i=1;i<=n;i++) { if(s[i]=='A') { a[i]+=a[i-1]+q[i]; b[i]=b[i-1]; } else { b[i]+=b[i-1]+q[i]; a[i]=a[i-1]; } } ans=b[n]; for(int i=1;i<=n;i++) { if(a[i]>b[i]) { ans=max(ans,a[i]+b[n]-b[i]); } } CLR(a,0);CLR(b,0); for(int i=n;i>=1;i--) { if(s[i]=='A') { a[i]+=a[i+1]+q[i]; b[i]=b[i+1]; } else { b[i]+=b[i+1]+q[i]; a[i]=a[i+1]; } } for(int i=n;i>=1;i--) { if(a[i]>b[i]) { ans=max(ans,a[i]+b[1]-b[i]); } } cout<<ans<<endl; return 0; }
题意:给你n个字符串,输出这n个串组合成的字符串字典序最小。
分析:直接排序输出是按每个串本身字典序排,整体并不是最小的。由于是要组合后的,所以我们定义排序规则 (a+b)<(b+a)。这样就可以让整体最小了。
代码:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<queue> #include<cmath> #include<stack> #include<set> #include<map> #define INF 0x3f3f3f3f #define Mn 1001000 #define Mm 2000005 #define mod 1000000007 #define CLR(a,b) memset((a),(b),sizeof((a))) #define CPY(a,b) memcpy ((a), (b), sizeof((a))) #pragma comment(linker, "/STACK:102400000,102400000") #define ul u<<1 #define ur (u<<1)|1 using namespace std; typedef long long ll; bool cmp(string a,string b) { return (a+b)<(b+a); } string s[Mn]; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { cin>>s[i]; } sort(s+1,s+1+n,cmp); for(int i=1;i<=n;i++) cout<<s[i]; return 0; }
题意:给出n个数,让你输出l,k,n个数中k个数的LCM,要求k最大的最小l。
分析:由于LCM不超过m(m<10^6),记录每个数的个数,从m到1,枚举这些数的倍数,a[i*j]+=a[i].最后找出最大。
代码:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<queue> #include<cmath> #include<stack> #include<set> #include<map> #define INF 0x3f3f3f3f #define Mn 1000010 #define Mm 2000005 #define mod 1000000007 #define CLR(a,b) memset((a),(b),sizeof((a))) #define CPY(a,b) memcpy ((a), (b), sizeof((a))) #pragma comment(linker, "/STACK:102400000,102400000") #define ul u<<1 #define ur (u<<1)|1 using namespace std; typedef long long ll; int a[Mn],b[Mn]; int main() { int n,m,x; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&b[i]); if(b[i]<=m) a[b[i]]++; } for(int i=m;i>=1;i--) { if(a[i]) { for(int j=2;i*j<=m;j++) { a[i*j]+=a[i]; } } } int ans=0,pos=0; for(int i=1;i<=m;i++) { if(a[i]>ans) { ans=a[i]; pos=i; } } if(pos) { cout<<pos<<" "<<ans<<endl; for(int i=1;i<=n;i++) { if(pos%b[i]==0) cout<<i<<" "; } }else cout<<1<<" "<<0<<endl; return 0; }
题意:不会。。。。
分析:
代码:
题意:给你一个n*n的矩阵,要你判断是否满足a[i][j]=0,a[i][j]=a[j][i],对于任意k满足a[i][j]<=max(a[i][k],a[j][k]).
分析: 由于对称,可以最后一个条件转换成a[i][j]<=max(a[i][k],a[k][j]),将矩阵上的a[i][j]看成点i到点j边长为a[i][j]。
然后就可以发现这个条件变成,a[i][j]小于等于i到j路径上的每条边。求个最小生成树。
代码:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<queue> #include<cmath> #include<stack> #include<set> #include<map> #define INF 0x3f3f3f3f #define Mn 2510 #define Mm 2000005 #define mod 1000000007 #define CLR(a,b) memset((a),(b),sizeof((a))) #define CPY(a,b) memcpy ((a), (b), sizeof((a))) #pragma comment(linker, "/STACK:102400000,102400000") #define ul u<<1 #define ur (u<<1)|1 using namespace std; typedef long long ll; int vt[Mn*Mn/2]; int a[Mn][Mn],cnt=0,n,pre[Mn]; bool cmp(int x,int y) { return a[x/n][x%n]<a[y/n][y%n]; } int find(int x) { if(x!=pre[x]) return pre[x]=find(pre[x]); return pre[x]; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) scanf("%d",&a[i][j]); pre[i]=i; } for(int i=1;i<=n;i++) { if(a[i][i]) {printf("NOT MAGIC\n");return 0;} for(int j=1;j<=n;j++) { if(a[i][j]!=a[j][i]) {printf("NOT MAGIC\n");return 0;} if(i>j) vt[cnt++]=i*n+j; } } int k=0; sort(vt,vt+cnt,cmp); for(int i=0;i<cnt;i++) { if(i<cnt&&a[vt[i]/n][vt[i]%n]==a[vt[i+1]/n][vt[i+1]%n]) continue; for(int j=k;j<=i;j++) if(find(vt[j]/n)==find(vt[j]%n)) {printf("NOT MAGIC\n");return 0;} for(int j=k;j<=i;j++) { int x=find(vt[j]/n); int y=find(vt[j]%n); if(x!=y) pre[x]=y; } k=i+1; } printf("MAGIC\n"); return 0; }