Codeforces Round #110 (Div. 1)
来源:互联网 发布:流量控制软件 编辑:程序博客网 时间:2024/04/29 16:34
codeforces一个不错的比赛,虽然我现在还不能参加div1的比赛,但是我还是好好的看了看昨天的那套题。不错!!
A:Message 这个题栽在了读题上,Insert one letter to any end of the string. 就是这句话,我怎么也没想到,其中的end是端点的意思,也就是在任意一个端点插入字母。好吧,我承认我英语不咋地,其他的倒是还好想,s的第i个字符和u的第j个字符是对应的,u的j后面的字符是插入的,这样的话,修改的次数就可以唯一的求出,进而求出结果。为了处理在前面插入的情况,在第一个字符串前面插入2000个字符就是了,前面插入相当于前面修改,ok,结束:
#include <iostream>#include <string.h>#include <stdio.h>using namespace std;#define N 2020char a[N*2],b[N];int data[N][N*2];int main(){ scanf("%s",a); scanf("%s",b); int aa = strlen(a); for(int i = 0;i <= aa;i++) a[i+2002] = a[i]; for(int i = 0;i < 2002;i++) a[i] = '@'; aa = strlen(a); int bb = strlen(b); //for(int i = aa+1;i > 0;i++) a[i] = a[i-1]; //for(int i = bb+1;i > 0;i++) b[i] = b[i-1]; for(int i = 0;i < 2010;i++) for(int j = 0;j < i;j++) data[i][j] = 200000; data[0][0] = 0; int re = 900000000; for(int i = 1;i <= bb;i++) for(int j = i;j <= aa;j++) { if(b[i-1] == a[j-1]) data[i][j] = data[i-1][j-1]; else data[i][j] = data[i-1][j-1]+1; re = min(re,bb-i+data[i][j]); } cout << re << "\n"; return 0;}
B:Suspects 这个题,也是有一点技巧的,我觉得挺好玩的。
题目大意是说,n个犯罪嫌疑人中有一个罪犯,n个犯罪嫌疑人分别说一句话:某某是犯罪分子或者某某不是犯罪分子。告诉你有m个说的真话,最后要求输出的是,这n个人时撒谎是说真话,还是不确定。
思路:首先注意这n个人中只有一个是犯罪分子,另一个要注意的是有m个人说了真话
可以先假设,所有人都不是犯罪分子,那么就会确定出k个人撒了谎,当我们再分别假设每一个人时犯罪分子,修正这个k,看说谎的人数和题目给的是否相同,如果相同,那么这个假设是犯罪分子的,就有可能是犯罪分子,否则,这个假设的人一定不是犯罪分子。
然后根据可能是犯罪分子的人的数量分类讨论输出就行了。
#include <iostream>#include <stdio.h>#include <string.h>using namespace std;#define N 100010int data[N][2];//0¼Ù£¬1Õæbool canFalse[N];int canFalseNum;int souse[N];int main(){ memset(data,0,sizeof(data)); memset(canFalse,0,sizeof(canFalse)); canFalseNum = 0; int fals = 0; int n,m,t; cin >> n >> m; for(int i = 1;i <= n;i++) { cin >> t; souse[i] = t; if(t > 0) { fals++; data[t][0]++; }else { t = 0-t; data[t][1]++; } } for(int i = 1;i <= n;i++) { if(fals - data[i][0] + data[i][1] == n-m) { canFalse[i] = 1; canFalseNum++; } } if(canFalseNum == 1) { for(int i = 1;i <= n;i++) { if( (souse[i] < 0 && canFalse[ 0-souse[i] ] == 0) || (souse[i] > 0 && canFalse[ souse[i] ] == 1) ) cout << "Truth\n"; else cout << "Lie\n"; } } else { for(int i = 1;i <= n;i++) { if( (souse[i] > 0 && canFalse[ souse[i] ] == 1) || (souse[i] < 0 && canFalse[ 0-souse[i] ] == 1) ) cout << "Not defined\n"; else if(souse[i] > 0 && canFalse[ souse[i] ] == 0 ) cout << "Lie\n"; else cout << "Truth\n"; } } return 0;}
C. Cipher 这个题,打死我我也想不出来啊!
题目大意:给出一个由26个小写字母构成的字符串,现在对其进行任意次修改,修改的规则是相邻两个字母一个增加一,一个减少一。如bc可以变成ad or cb。
通过任意次修改之后,总共能产生多少个和自己不相同的字符串。
思路:首先要注意的是,这个结果只与两个值有关:字符串的长度,每个字符的和。 证明我还是不会,但是可以想明白,首先可以得出的结论是,如果一个字符增加了1那么任意一个其他的字符就得减1,注意这里的是任意。也就是说,只要和相同,结果就相同。
很有意思!!
之后的问题就不难了!!
#include <iostream>#include <stdio.h>#include <string.h>using namespace std;#define P 1000000007long long dp[110][2700];int main(){ memset(dp,0,sizeof(dp)); for(int i=0;i<26;i++) dp[1][i]=1; for(int i=2;i<=100;i++) { for(int j=0;j<=2600;j++) for(int k=0;k<26;k++) dp[i][j+k]=(dp[i][j+k]+dp[i-1][j])%P; } int t; char ch[110]; cin >> t; while(t--) { scanf("%s",ch); int len = strlen(ch); int sum = 0; for(int i = 0;i < len;i++) sum += ch[i]-'a'; cout << (dp[len][sum]+P -1)%P << "\n";; } return 0;}
D. Clues
很容易想到的是,把相连的图缩成一个点。然后就是求生成树的个数问题!
但是这个到底怎么处理呢?、
我记得有这么一个公式:Kn的生成树个数为:n^(n-2)
这个公式叫做Cayley公式。有一个有趣的证明,http://www.matrix67.com/blog/archives/682 其中用到了Prüfer编码
这个与那个不同的是,这个每一个点都是有好多个点缩成的,然后公式就有些变化,
#include <iostream>#include <string.h>#include <stdio.h>using namespace std;#define N 100010bool vis[N];struct note{ int v,next;}edge[N*3];int head[N],kk;void add(int from,int to){ edge[kk].next = head[from]; edge[kk].v = to; head[from] = kk++;}int cnt;void dfs(int root){ if(vis[root]) return ; cnt++; vis[root] = 1; for(int i = head[root];i != -1;i = edge[i].next) dfs(edge[i].v);}int main(){ int n,m,p; cin >> n >> m >> p; int a,b; kk = 1;memset(head,-1,sizeof(head)); for(int i = 0;i < m;i++) { scanf("%d%d",&a,&b); add(a,b);add(b,a); } memset(vis,0,sizeof(vis)); long long sum = 0,re = 1; int k = 0; for(int i = 1;i <= n;i++) { if(vis[i] == 0) { cnt = 0; dfs(i); k++; sum = (sum + cnt)%p; re = (re * cnt)%p; } } for(int i = 1;i <= k-2;i++) re = (re * sum)%p; if(k == 1) cout << 1%p << "\n"; else cout << re << "\n"; return 0;}
我个人感觉这套题目挺好的。
如果有不对的地方,欢迎交流。
- Codeforces Round #110 (Div. 1)
- 【dp】Codeforces Round #110 (Div. 1) C
- Codeforces Round #110 (Div. 2)
- Codeforces Round #110 (Div. 2)
- Codeforces Round #138 (Div. 1)
- Codeforces Round #140 (Div. 1)
- Codeforces Round #153 (Div. 1)
- Codeforces Round #157 (Div. 1)
- Codeforces Round #160 (Div. 1)
- Codeforces Round #162 (Div. 1)
- Codeforces Round #165 (Div. 1)
- Codeforces Round #165 (Div. 1)
- Codeforces Round #167 (Div. 1)
- Codeforces Round #168 (Div. 1)
- Codeforces Round #174 (Div. 1)
- Codeforces Round #187 DIV 1
- Codeforces Round #198 (Div. 1)
- Codeforces Round #198 (Div. 1)
- 我们都是物联网里的“things”
- 指针(二)
- 指针(三)
- 3dmax模型导入插件
- FineReport 批量打印 无提示
- Codeforces Round #110 (Div. 1)
- 通过构造Hash冲突实现各种语言的拒绝服务攻击
- Windows to go 把Windows8装到你的U盘里
- Resin学习笔记
- 使用OCR来帮助LR实现认证码识别 By 云层
- Error in OMNeT++ 4.1 over Ubuntu 11.10
- 类库设计系列:类库的基本架构
- c语言实现函数可变参数
- linux下的postgrel9.0安装