1004.Tokitsukaze and Multiple
一个长度为n的序列,用a表示,可以把两个位置连续的数合并多次,每次操作后新元素等于两个旧元素之和,a的长度减少1;
求对a进行某些操作(或不进行操作)后可以得到的p的倍数的最大可能元素数。
思路:
对a数组进行求前缀和并模p,这样如果出现相同的数,则中间的数之和等于p的倍数。
(回顾另一个前缀和的性质,没有模,直接前缀和:如果某个前缀出现了和前面一个前缀一样的和,那么中间的数的和为0。)
用map记录前缀和并模p的值,如果当前的值出现过,那么就合并,ans++,能合并就合并。
具体见代码:
#include <bits/stdc++.h> using namespace std; const long long mod=1e9+7; typedef long long ll; const int inf=0x3f3f3f3f; const long long INF=0x3f3f3f3f3f3f3f3f; const int MAXN=1e5+5; const double eps=-1e8; typedef pair<int,int>pii; ll a[MAXN]; map<int,int>mp; int main() { int t; scanf("%d",&t); while(t--) { mp.clear(); int n; ll p; ll sum=0; scanf("%d%lld",&n,&p); mp[0]=1; int ans=0; for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); sum=(sum+a[i])%p; if(mp[sum]>0) { ans++; mp.clear(); mp[0]=1; sum=0; } else mp[sum]++; } printf("%d\n",ans); } return 0; }
dp做法:
#include <bits/stdc++.h> using namespace std; const long long mod =1e9+7; typedef long long ll; const int inf =0x3f3f3f3f; const long long INF =0x3f3f3f3f3f3f3f3f; const int MAXN =2e5+5; ll a[MAXN]; ll sum[MAXN]; int vis[MAXN]; int dp[MAXN]; int main() { int t; scanf("%d",&t); while(t--) { int n; ll m; ll ans=0; scanf("%d%lld",&n,&m); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); sum[i]=(sum[i-1]+a[i])%m; dp[i]=dp[i-1]; if(vis[sum[i]]!=0||sum[i]==0)dp[i]=max(dp[i],dp[vis[sum[i]]]+1); vis[sum[i]]=i; } printf("%d\n",dp[n]); for(int i=0;i<=n;i++)dp[i]=0,vis[i]=0; } return 0; }
1005.Little W and Contest
并查集+组合数。
代码:
#include <bits/stdc++.h> using namespace std; const long long mod =1e9+7; typedef long long ll; const int inf =0x3f3f3f3f; const long long INF =0x3f3f3f3f3f3f3f3f; const int MAXN =2e5+5; ll fac[MAXN],invfac[MAXN],inv[MAXN]; int f[MAXN]; ll num[MAXN][5]; int Find(int n) { if(f[n]==n)return n; f[n]=Find(f[n]); return f[n]; } void Union(int a,int b) { int fa=Find(a); int fb=Find(b); if(fa!=fb) { f[fa]=fb; num[fb][1]+=num[fa][1]; num[fb][2]+=num[fa][2]; } } void init(int n) { invfac[0]=1; fac[0]=1; inv[1]=1; for(int i=2;i<=n;++i) inv[i]=((mod-mod/i)*inv[mod%i])%mod; for(int i=1;i<=n;++i) fac[i]=fac[i-1]*i%mod,invfac[i]=invfac[i-1]*inv[i]%mod; } ll C(int n,int m) { return fac[n]*invfac[m]%mod*invfac[n-m]%mod; } int main() { init(100005); int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); ll sum1=0,sum2=0; for(int i=1;i<=n;i++) { int a; scanf("%d",&a); if(a==1)sum1++; else sum2++; f[i]=i; num[i][a]++; } ll ans=((C(sum2,2)*sum1)%mod+C(sum2,3))%mod; printf("%lld\n",ans); for(int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); int fu=Find(u); int fv=Find(v); ll tmp=(((num[fu][2]*num[fv][2])%mod*(sum1-num[fu][1]-num[fv][1]))%mod+((num[fu][2]*num[fv][2])%mod*(sum2-num[fu][2]-num[fv][2]))%mod)%mod;//每次在合并之前算合并后会减少的值 tmp=(tmp+((num[fu][2]*num[fv][1])%mod*(sum2-num[fu][2]-num[fv][2]))%mod+((num[fv][2]*num[fu][1])%mod*(sum2-num[fu][2]-num[fv][2]))%mod)%mod; ans=(ans-tmp+mod)%mod; printf("%lld\n",ans); Union(fu,fv); } for(int i=1;i<=n;i++) { num[i][1]=0; num[i][2]=0; } } return 0; }
1009.Parentheses Matching
括号匹配。
代码:
#include <bits/stdc++.h> using namespace std; const long long mod =1e9+7; typedef long long ll; const int inf =0x3f3f3f3f; const long long INF =0x3f3f3f3f3f3f3f3f; const int MAXN =2e5+5; char a[MAXN]; char b[MAXN]; int l[MAXN],r[MAXN]; int main() { int t; scanf("%d",&t); while(t--) { int len; scanf("%s",a+1); len=strlen(a+1); int flag=0; int l0=0,r0=0; int cntl=0; for(int i=1;i<=len;i++) { if(a[i]=='*'||a[i]=='(') { l0++; if(a[i]=='(') { l[i]=l[i-1]+1; r[i]=r[i-1]; } else { l[i]=l[i-1]; r[i]=r[i-1]; } } else { r0++; r[i]=r[i-1]+1; l[i]=l[i-1]; } cntl=max(r[i]-l[i],cntl); if(r0>l0){flag=1;break;} } r0=0,l0=0; for(int i=len;i>=1;i--) { if(a[i]=='*'||a[i]==')')l0++; else r0++; if(r0>l0){flag=1;break;} } if(flag) { printf("No solution!\n"); continue; } int cntr=l[len]+cntl-r[len]; for(int i=1;i<=len;i++) { if(a[i]=='*'&&cntl>0)a[i]='(',cntl--; } for(int i=len;i>=1;i--) { if(a[i]=='*'&&cntr>0)a[i]=')',cntr--; } for(int i=1;i<=len;i++) { if(a[i]!='*')printf("%c",a[i]); } printf("\n"); for(int i=0;i<=len+10;i++) { l[i]=0; r[i]=0; } } return 0; } /* 10 ))** ))(( (**)() *)() ****( *****) ())***() (((**() */