A. Bulbs
题目描述:
就是有m盏灯,有n个开关,一开始灯都是关的,然后按下一个开关后就会使某些灯打开,然后打开的灯不会再次熄灭。问能否是所有的灯打开。
解答:
简单的遍历一下,然后看是否存在有灯不受开关控制。
#include <iostream>
using namespace std;
int num[105], n, m;
void solve()
{
int cnt = 0;
for(int i = 0; i < m; i ++) num[i] = 0;
int geshu, val;
for(int i = 0; i < n; i ++){
cin>>geshu;
for(int j = 0; j < geshu; j ++){
cin>>val;
if(num[val -= 1] == 0)
cnt ++;
num[val] = 1;
}
}
cout<< ((cnt == m) ? "YES" : "NO") <<endl;
}
int main()
{
while(cin>>n>>m){
solve();
}
}
B. Longtail Hedgehog
题目描述:
就是可以用别画个dog,然后每个点有一个数字,然后告诉你m对连接的数字,dog由脊柱和尾巴构成,脊柱为数字,只能从小到大构成脊柱,尾巴可以为多条,长度为1。现在定义一个值,该值是由尾巴的条数乘以脊柱的长度的积得到,现在要求这个值的最大值。
解答:
因为脊柱数字时从小到大的,那么在求解脊柱长度时,可以得到五环有向图,然后针对有向图求度数,运用DAG+dp可以得到每个点的深度的最大值,即脊柱的最大值,然后根据无向图的该点边的个数,可以得到尾巴长度。然后遍历一下求最大值即可。
#include <iostream>
#include <queue>
#include <cmath>
#include <cstdio>
using namespace std;
int n, m, dree[100005], dushu[100005];
vector<int> G[100005];
bool isVisit[100005];
void solve()
{
fill(dree, dree + n, 0);
fill(dushu, dushu + n, 0);
for(int i = 0; i < n; i ++) G[i].clear();
int u, v;
for(int i = 0; i < m; i ++){
cin>>u>>v;
u -= 1, v -= 1;
if(u > v) swap(u, v);
G[u].push_back(v);
G[v].push_back(u);
dushu[v] ++;
}
queue<int> q;
for(int i = 0; i < n; i ++){
if(dushu[i] == 0){
dree[i] = 1;
q.push(i);
}
}
while(!q.empty()){
int t = q.front();
q.pop();
int len = G[t].size();
for(int i = 0; i < len; i ++){
if(G[t][i] < t) continue;
dree[G[t][i]] = max(dree[G[t][i]], dree[t] + 1);
dushu[G[t][i]] --;
if(dushu[G[t][i]] == 0) q.push(G[t][i]);
}
}
fill(isVisit, isVisit + n, false);
__int64 ans = 0;
for(int i = 0; i < n; i ++){
ans = max(ans, 1LL * G[i].size() * dree[i]);
}
cout<<ans<<endl;
}
int main()
{
while(cin>>n>>m){
solve();
}
}
C.
Running Track
题目描述:
就是有两个字符串s,t。然后t可以分成很多子串,这些子串必须出现在s中,或者s的翻转串中,问分成子串个数最少的方案。
解答:
题目数据量不大字符串的长度为2100,所以运用最大匹配的方法,例如t的前i个字符能在s或者f反s中找到,且前i+1个不能在二者中找到,那么这前i个字符就是子串之一,一直这样进行下去。查找时,使用KMP,时间复杂度为O(n^2)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int Next[2105];
void getNext(char *s)
{
int len = strlen(s);
fill(Next, Next + len, -1);
int i = 0, j = -1;
while(i < len){
if(j == -1 || s[i] == s[j]){
i ++, j ++;
if(i >= len) break;
if(s[i] != s[j]) Next[i] = j;
else Next[i] = Next[j];
}
else j = Next[j];
}
}
int Kmp(char *s1, char *s2)
{
int len1 = strlen(s1), len2 = strlen(s2), i = 0, j = 0, st = 0;
while(i < len1){
if(j != -1 && s1[i] == s2[j]){
i ++, j ++;
if(j >= len2) return i - strlen(s2);
}
else j = Next[j];
if(j == -1){
i ++;
st = i;
j = 0;
}
}
return -1;
}
char s1[2103], s2[2103], s3[2103], s4[2103];
int cnt, st[2103], et[2103];
void solve()
{
int len1 = strlen(s1), len2 = strlen(s2);
for(int i = 0; i <= len2 / 2; i ++)
s3[i] = s2[len2 - i - 1], s3[len2 - i - 1] = s2[i];
s3[len2] = 0;
cnt = 0;
int curSt = 0;
int ans1, ans2;
s4[0] = 0;
for(int i = 0; i < len1; i ++){
if(curSt == i){
s4[0] = s1[i];
s4[1] = 0;
}
else{
int len = strlen(s4);
s4[len] = s1[i];
s4[len + 1] = 0;
}
getNext(s4);
int t = Kmp(s2, s4);
if(t == -1){
t = Kmp(s3, s4);
if(t == -1){
if(curSt == i){
cout<<"-1"<<endl;
return;
}
else{
st[cnt] = ans1;
et[cnt] = ans2;
cnt ++, curSt = i;
i --;
}
}
else{
ans1 = len2 - 1 - t;
ans2 = len2 - 1 - (t + i - curSt);
}
}
else{
ans1 = t;
ans2 = t + i - curSt;
}
}
st[cnt] = ans1;
et[cnt] = ans2;
cout<<cnt + 1<<endl;
for(int i = 0; i <= cnt; i ++)
cout<<st[i] + 1<<" "<<et[i] + 1<<endl;
}
int main()
{
while(cin>>s2>>s1){
solve();
}
}
D.
Multipliers
题目描述:
就是告诉你一个数可以有p1p2....pm个数相乘得到,且每个pi都是素数。现在要求该数所有因子的乘积,最后结果Mod(10^9 + 7)。
解答:
题目的意思很好理解,假设对p进行排序合并之后,可以得到该数如下表示
对于p的贡献进行分析,所有因子中含有p,且除以p之后不能被p整除的个数为(b + 1)(c + 1)个,对于含有p^2的因子个数也是这么多个,所以对于p的贡献积为
对于q,r同理可得,最后的表达式为:
根据上面的式子进行求解即可,注意一些小细节的处理
#include <iostream>
#include <algorithm>
using namespace std;
__int64 num[200005], ans;
int cnt[200005];
int m;
const int Mod = 1000000007;
void powV(__int64 temp, int n)
{
while(n){
if(n & 1)
ans = (ans * temp) % Mod;
temp = temp * temp % Mod;
n >>= 1;
}
}
__int64 powVV(__int64 temp, int n)
{
__int64 aannss = 1;
while(n){
if(n & 1)
aannss = (aannss * temp) % Mod;
temp = temp * temp % Mod;
n >>= 1;
}
return aannss;
}
void solve()
{
for(int i = 0; i < m; i ++) cin>>num[i];
sort(num, num + m);
int len = m;
bool isAllEven = true;
cnt[0] = 1;
for(int i = 1, j = 0; i < m; i ++){
if(num[i] != num[j]){
if(cnt[j] % 2) isAllEven = false;
j ++;
num[j] = num[i];
cnt[j] = 1;
}
else{
cnt[j] ++;
len --;
}
}
if(cnt[len - 1] % 2) isAllEven = false;
ans = 1;
for(int i = 0; i < len; i ++)
powV(num[i], isAllEven ? cnt[i] / 2 : cnt[i]);
for(int i = 0; i < len; i ++){
if(!isAllEven && cnt[i] % 2){
ans = powVV(ans, (cnt[i] + 1) / 2);
isAllEven = true;
}
else
ans = powVV(ans, (cnt[i] + 1));
}
cout<<ans<<endl;
}
int main()
{
while(cin>>m){
solve();
}
}
E. Hexagons
找规律题,以后再补吧,也有可能 不补。