【codeforces #295(div 1)】ABC题解
来源:互联网 发布:火狐javascript void 0 编辑:程序博客网 时间:2024/06/02 06:43
很慢得速度做完了A;
B一直WA,考完才发现读错题了;
考完发现C也很简单。。
先说A题:
Vasya became interested in bioinformatics. He's going to write an article about similar cyclic DNA sequences, so he invented a new method for determining the similarity of cyclic sequences.
Let's assume that strings s and t have the same length n, then the function h(s, t) is defined as the number of positions in which the respective symbols of s and t are the same. Function h(s, t) can be used to define the function of Vasya distance ρ(s, t):
Vasya found a string s of length n on the Internet. Now he wants to count how many strings t there are such that the Vasya distance from the string s attains maximum possible value. Formally speaking, t must satisfy the equation: .
Vasya could not try all possible strings to find an answer, so he needs your help. As the answer may be very large, count the number of such strings modulo 109 + 7.
The first line of the input contains a single integer n (1 ≤ n ≤ 105).
The second line of the input contains a single string of length n, consisting of characters "ACGT".
Print a single number — the answer modulo 109 + 7.
1C
1
2AG
4
3TTT
1
Please note that if for two distinct strings t1 and t2 values ρ(s, t1) и ρ(s, t2) are maximum among all possible t, then both strings must be taken into account in the answer even if one of them can be obtained by a circular shift of another one.
In the first sample, there is ρ("C", "C") = 1, for the remaining strings t of length 1 the value of ρ(s, t) is 0.
In the second sample, ρ("AG", "AG") = ρ("AG", "GA") = ρ("AG", "AA") = ρ("AG", "GG") = 4.
In the third sample, ρ("TTT", "TTT") = 27
贪心~
去掉前一个sigma,发现第二个sigma相当于让每个数字经过一次每个位置,如果新串的这个位置和当前数字相同,那么对答案贡献1。那么如果一个字母出现k次,在每一个位置对答案的贡献都是k。
而第一个sigma相当于对答案*n。
要让答案最大,就让每一位对答案的贡献都最大即可,也就是让每一位都是出现次数最多的那个字母。
那么答案就是出现次数最多的字母的种类数的n次方。
#include <iostream>#include <algorithm>#include <cstring>#include <cstdio>#include <cmath>#define LL long longusing namespace std;int n,a[10];char c[100005];void Pow(int k,int n){LL mod=(LL)1000000007;long long ans=1LL;for (int i=1;i<=n;i++)ans=(ans*(LL)k)%(LL)mod;cout<<ans<<endl;}int main(){scanf("%d",&n);scanf("%s",c); for (int i=1;i<=n;i++){char x;x=c[i-1];if (x=='A') a[1]++;if (x=='C') a[2]++;if (x=='G') a[3]++;if (x=='T') a[4]++;}int k=0,ma=max(a[1],max(a[2],max(a[3],a[4])));for (int i=1;i<=4;i++)if (a[i]==ma) k++;Pow(k,n);return 0;}
只要STL用的熟练,这题就非常简单了。
我们把当前可以拆卸的加入到set中。
什么是可以拆卸的?
1.没有被他支撑的 2.被他支撑的块的支撑物>1
然后从set中取最大/小的出来,更新set:可能是某些块能加入了,可能是某些块不能拆卸了。
注意被更新的块一定位于当前块(x,y)的x+1/x-1层,y+-1,y+-2处。
(为什么会影响y+-2处呢?因为如果(x+1,y+1)处只有(x,y)和(x,y+2)支撑,那么此时(x,y+2)就得从set中取出了)
#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>#include <cmath>#include <queue>#define mod 1000000009#define LL long long#define M 100010#include <vector>#include <map>#include <set>#define mp make_pairusing namespace std;map<pair<int,int>,int> used;int m;set<int> s;struct Point{int x,y;}a[M];int Calc(int x,int y){int ans=0;for (int i=-1;i<=1;i++)if (used[mp(x+i,y-1)]) ans++;return ans;}void Judge(int x,int y){int ok=1;for (int i=-1;i<=1;i++)if (used[mp(x+i,y+1)]&&Calc(x+i,y+1)==1)ok=0;if (!ok){if (s.count(used[mp(x,y)])) s.erase(used[mp(x,y)]);}else {if (!s.count(used[mp(x,y)])) s.insert(used[mp(x,y)]);}}int main(){cin>>m;for (int i=1;i<=m;i++){scanf("%d%d",&a[i].x,&a[i].y);used[mp(a[i].x,a[i].y)]=i;}for (int i=1;i<=m;i++)Judge(a[i].x,a[i].y);LL ans=0LL;for (int i=1;i<=m;i++){int x;if (i&1){x=*s.rbegin();s.erase(x);ans=(1LL*ans*m+x-1)%mod;}else{x=*s.begin();s.erase(x);ans=(1LL*ans*m+x-1)%mod;}used[mp(a[x].x,a[x].y)]=0;for (int i=-2;i<=2;i++)for (int j=-1;j<=1;j++)if (used[mp(a[x].x+i,a[x].y+j)]) Judge(a[x].x+i,a[x].y+j);}cout<<ans<<endl;return 0;}
C:
Vasya is sitting on an extremely boring math class. To have fun, he took a piece of paper and wrote out n numbers on a single line. After that, Vasya began to write out different ways to put pluses ("+") in the line between certain digits in the line so that the result was a correct arithmetic expression; formally, no two pluses in such a partition can stand together (between any two adjacent pluses there must be at least one digit), and no plus can stand at the beginning or the end of a line. For example, in the string100500, ways 100500 (add no pluses), 1+00+500 or 10050+0 are correct, and ways 100++500, +1+0+0+5+0+0 or100500+ are incorrect.
The lesson was long, and Vasya has written all the correct ways to place exactly k pluses in a string of digits. At this point, he got caught having fun by a teacher and he was given the task to calculate the sum of all the resulting arithmetic expressions by the end of the lesson (when calculating the value of an expression the leading zeros should be ignored). As the answer can be large, Vasya is allowed to get only its remainder modulo 109 + 7. Help him!
The first line contains two integers, n and k (0 ≤ k < n ≤ 105).
The second line contains a string consisting of n digits.
Print the answer to the problem modulo 109 + 7.
3 1108
27
3 2108
9
In the first sample the result equals (1 + 08) + (10 + 8) = 27.
In the second sample the result equals 1 + 0 + 8 = 9.
一个数字x对答案的贡献可能为x*10^l(l=0,1,2...),那么我们分别计算x对答案贡献为x,10x,100x...时加号的方案数。
1.对答案贡献为x*10^l的加号方案数为C(n-2-l,k-1),也就是说在x的l位之后必定有一个加号,剩余的k-1个加号填在别的地方;这样一个一个直接算会超时,我们发现每一个数对答案的贡献都是数本身*10^l是,无论x是几,方案数都一样,因此可以枚举l,维护前缀和,直接计算所有数。
2.还要注意,如果x是出现在最后一个数字中,那么他的l位之后是没有加号的,此时x对答案的贡献是固定的,方案数为(x是第i个数)C(i-1,k),把这种情况单独加上即可。
#include <iostream>#include <algorithm>#include <cstring>#include <cstdio>#include <cstdlib>#define mod 1000000007#define LL long long#define M 100000+5using namespace std;char s[M];LL a[M],sum[M],inv[M],fac[M],ten[M];int n,k;LL Getinv(LL x){int n=mod-2;LL ans=1LL,base=x;while (n){if (n&1) ans=ans*base%mod;base=base*base%mod;n>>=1;}return ans;}void Prepare(){fac[0]=inv[0]=1LL;for (int i=1;i<=n;i++)fac[i]=fac[i-1]*(LL)i%mod;for (int i=1;i<=n;i++)inv[i]=Getinv(fac[i]);ten[0]=1LL;for (int i=1;i<=n;i++)ten[i]=ten[i-1]*10LL%mod;}LL Getc(int n,int m){if (n<m) return 0LL;return fac[n]*inv[m]%mod*inv[n-m]%mod;}int main(){ scanf("%d%d",&n,&k);Prepare();sum[0]=0LL;scanf("%s",s);for (int i=1;i<=n;i++){a[i]=(LL)(s[i-1]-'0');sum[i]=sum[i-1]+a[i];}LL ans=0LL;for (int l=0;l<=n-2;l++){LL x=sum[n-1-l]*ten[l]%mod;ans=(ans+(x*Getc(n-l-2,k-1)%mod))%mod;}for (int i=1;i<=n;i++)ans=(ans+ten[n-i]*a[i]%mod*Getc(i-1,k)%mod)%mod;cout<<ans<<endl;return 0;}
感悟:
1.CF对STL的考察很多,一定要好好掌握。
2.思考速度要加快!!
- 【codeforces #295(div 1)】ABC题解
- 【codeforces #292(div 1)】ABC题解
- 【codeforces #290(div 1)】ABC题解
- 【codeforces #284(div 1)】ABC题解
- 【codeforces #283(div 1)】ABC题解
- 【codeforces #299(div 1)】ABC题解
- [Codeforces Round #309 (Div. 2)] #ABC题解
- [Codeforces Round #310 (Div. 2)] #ABC题解
- Codeforces Round #312 (Div. 2) ABC题解
- Codeforces Round #331 (Div. 2) (ABC题解)
- Codeforces Round #418 (Div. 2) 题解 ABC
- Codeforces Round #259 (Div. 2) ABC简要题解
- Codeforces Round #323 (Div. 2) ABC题解(全是暴力)
- Codeforces Round #325 (Div. 2) 586ABC题解
- Codeforces Round #326 (Div. 2) 588ABC题解
- Codeforces Round #327 (Div. 2) 591ABC题解
- Codeforces Round #328 (Div. 2) 592ABC题解
- Codeforces Round #331 (Div. 2) 596ABC题解
- ConcurrentHashMap
- JAVAEE----JavaScript知识点总结
- C++多态的实现原理【转】
- 点方法并不需要@property
- MySql 创建表的时候保留大小写状态
- 【codeforces #295(div 1)】ABC题解
- Android volley 解析(四)之缓存篇
- Android Studio导入GitHub上的项目常见问题(以图片轮播开源项目为实例)
- OpenGL Framebuffer Object (FBO)
- Mysql物理查询技术
- 双队列实现队列中元素排序
- cout流的重载
- AFNetworking NSURLErrorDomain error -1012
- Windows Phone 8.1添加后台任务运行条件(可添加多个)