题意:w数组为给定的一个可负数组,b数组中每个元素为+1或者-1,以及一个任意实数α>=0,使| wi-α*bi |^2的和为最小。
题解:那道题第一感觉α很有可能是wi的平均数,但是wa了,并没有发现哪里有问题,后来才发现其实把式子直接展开就好,可以的得到一个一元二次方程,对称轴处取最小值,满足时刚好上面的猜想是成立的。

#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long ll; ll gcd(ll a,ll b){ return b==0 ? a : gcd(b,a%b); } ll a[100005]; int main(){ int t; scanf("%d",&t); while(t--){ ll n; scanf("%lld",&n); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); ll x=0,y=0; for(int i=1;i<=n;i++){ x+=a[i]*a[i]; y+=abs(a[i]); } y=y*y; x=x*n; ll ans=x-y; printf("%lld/%lld ",ans/gcd(ans,n),n/gcd(ans,n)); } return 0; }
这个题没什么太多好说的,直接保证第1,2个值取最大(合分比性质),后面的值取最小就好。

#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; int gcd(int a,int b){ return b==0 ? a : gcd(b,a%b); } int a[105],vis[105]; int main(){ int t; scanf("%d",&t); while(t--){ int n,m; scanf("%d%d",&n,&m); int mix=1000; memset(vis,0,sizeof(vis)); for(int i=1;i<=m;i++){ int x,y; scanf("%d%d",&x,&y); a[x]=y; mix=min(mix,x); vis[x]=1; } int ans=0; if(mix==1000){ printf("%d/%d ",1,1); } else if(mix>2){ ans+=200; int cnt=0; for(int i=3;i<=n;i++){ if(!vis[i]) cnt++; else { ans+=((a[i])*(cnt+1)); cnt=0; } } printf("%d/%d ",200/gcd(200,ans),ans/gcd(200,ans)); } else if(mix==2){ ans+=100; int cnt=0; for(int i=2;i<=n;i++){ if(!vis[i]) cnt++; else { ans+=((a[i])*(cnt+1)); cnt=0; } } printf("%d/%d ",(100+a[mix])/gcd(ans,100+a[mix]),ans/gcd(ans,100+a[mix])); } else if(mix==1){ int cnt=0; int p=a[mix]; if(vis[2]) { p+=a[2]; ans=p; for(int i=3;i<=n;i++){ if(!vis[i]) cnt++; else { ans+=((a[i])*(cnt+1)); cnt=0; } } } else{ p*=2; ans=p; for(int i=3;i<=n;i++){ if(!vis[i]) cnt++; else { ans+=((a[i])*(cnt+1)); cnt=0; } } } printf("%d/%d ",p/gcd(ans,p),ans/gcd(ans,p)); } } return 0; }
题意:给出一定量的不同字符,要求用完所有字符组成一个或多个字符串使每一个字符串都为回文串,且长度最小的字符串长度最大
题解:此题只需要统计字符串有几个奇数个,以及能够组成几双偶数对。因为每一个字符可以被两个相同的字符包围着,所以尽可能多地使每一个单出来的字符被包围的次数相同。

#include<cstdio> #include<algorithm> #include<cstring> using namespace std; int a[100005]; int main(){ int t; scanf("%d",&t); while(t--){ int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); int odd=0,even=0; for(int i=1;i<=n;i++){ odd+=(a[i]%2); even+=(a[i]/2); } int ans=0; if(odd==0) ans=even*2; else{ ans=max(1,even/odd*2+1); } printf("%d ",ans); } return 0; }
题意:给出两个字符串s、p,长度分别为n、m,可以对p相邻的两个元素进行交换且每个字符只能交换一次,问s每一个位置往后延伸的m个个位置所组成的字符串能否有p变换得到。
题解:对于s的每一个位置,只需要考虑两种情况,往后交换和不交换(往前交换的情况会在前一个的往后交换中包含),如果往后交换满足p下的指标就增加1,以此来判断是否可以。

#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> using namespace std; char s[100005],p[100005]; int main(){ int t; scanf("%d",&t); while(t--){ int n,m; scanf("%d%d",&n,&m); scanf("%s%s",s,p); for(int i=0;i<n;i++){ bool flag=1; if(i>n-m){ printf("0"); continue; } for(int j=0;j<m;j++){ if(j<m-1&&s[i+j+1]==p[j]&&s[i+j]==p[j+1]) j++; else if(s[i+j]!=p[j]){ flag=0; break; } } printf("%d",flag); } printf(" "); } return 0; }