偷吃糖果
Description
Input
解题思路:
删除两个字符串所有连续重复字符,只剩下一个。在判定两个是否相同。
AC代码:
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
int main(){
int T;
scanf("%d",&T);
while(T--){
string str1,str2;
cin>>str1>>str2;
int len1 = str1.size();
int len2 = str2.size();
for(int i = 0; i < str1.size()-1;){
if(str1[i] == str1[i+1])
str1 = str1.substr(0,i)+str1.substr(i+1);
else
++i;
}
for(int i = 0; i < str2.size()-1;){
if(str2[i] == str2[i+1])
str2 = str2.substr(0,i)+str2.substr(i+1);
else
++i;
}
//cout<<str1<<endl;
//cout<<str2<<endl;
if(str1 == str2)
puts("Yes");
else
puts("No");
}
return 0;
}
count_prime
Description
Input
解题思路:
容斥原理、先对n分解质因数,分别记录每个质因数,那么所求区间内与某个质因数不互质的个数就是n/r(i),假设r(i)是r的某个质因子 假设只有三个质因子,总的不互质的个数应该为p1+p2+p3-p1p2-p1p3-p2p3+p1*p2*p3, 及容斥原理,pi代表n/r(i),即与某个质因子不互质的数的个数,当有更多个质因子的时候,可以用状态压缩解决,二进制位上是1表示这个质因子被取进去了。如果有奇数个1就相加,反之则相减。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
typedef long long ll;
vector<ll> prime;
ll make_ans(ll num,int m){
ll ans = 0,tmp,flag;
for(ll i = 1; i < (ll)(1<<m); ++i){ //用二进制来1,0来表示第几个素因子是否被用到,如m=3,三个因子是2,3,5,则i=3时二进制是011,表示第2、3个因子被用到
tmp = 1,flag = 0;
for(ll j = 0; j < m; ++j)
if(i & ((ll)(1<<j)))//判断第几个因子目前被用到
flag++,tmp *= prime[j];
if(flag & 1)//容斥原理,奇加偶减
ans += num/tmp;
else
ans -= num/tmp;
}
return ans;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
ll a,b,n;
prime.clear();
scanf("%lld%lld%lld",&a,&b,&n);
for(ll i = 2; i*i <= n; ++i){ //对n进行素因子分解
if(n && n%i==0){
prime.push_back(i);
while(n && n%i==0)
n /= i;
}
}
if(n > 1)
prime.push_back(n);
printf("%lld\n",(b-make_ans(b,prime.size()))-(a-1-make_ans(a-1,prime.size())));
}
return 0;
}
sequence
Description
Input
解题思路:
经典贪心问题,从前往后扫描原数组,每到一个数,找个当前最大值最大的不降数组加入其中,否则新建一个不降数组。
AC代码:
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
vector<int> v[2];
int main(){
int T;
scanf("%d",&T);
while(T--){
int x,n,k = 0;
scanf("%d",&n);
v[0].clear();
for(int i = 0; i < n; ++i){
scanf("%d",&x);
v[0].push_back(x);
}
int t = 0;
for(k = 0; k < n; ++k){
int len = v[t].size(),tmp;
if(len == 0)
break;
v[1-t].clear();
tmp = v[t][0];
for(int j = 1; j < len; ++j){
if(tmp > v[t][j])
v[1-t].push_back(v[t][j]);
else
tmp = v[t][j];
}
t = 1-t;
}
printf("%d\n",k);
}
return 0;
}
谁才是最强战舰!
Description
Input
解题思路:
奇异局势,所有堆的xor和==0.
假定S是非奇异局势,T是奇异局势。
一堆中石子数量>=2,表示充裕堆, =1表示孤单堆。
S0即非奇异局势下,充裕堆为0的状态
S1即非奇异局势下,充裕堆为1的状态
S2即非奇异局势下,充裕堆>=2的状态
T0即奇异局势下,充裕堆为0的状态
T2即奇异局势下,充裕堆>=2的状态
1.奇异局势的定义可知,S能转移到T,能转移到S, T只能转移到S
2.S0必败,T0必胜
3.S1必胜,因为S1只需要转移到S0即可。
4.S2必胜,T2必败。
1)T2只能转移到S1 和 S2
2)若T2转移到S1 则T2败,若T2转移到S2,S2只需要转回到T2即可。所以S2胜,T2败。
所以:
必胜态:T0,S1,S2
必败态:S0,T2
AC代码:
#include <iostream>
#include <cstdio>
using namespace std;
bool solve(){
int x,n,flag = 1,sum = 0;
scanf("%d",&n);
for(int i = 0; i < n; ++i){
scanf("%d",&x);
if(x^1)
flag = 0;
sum ^= x;
}
if(flag)
return !sum;
else
return sum;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
if(solve())
puts("Yamato_Saikou!");
else
puts("Meidikeji_Shijiediyi!");
}
return 0;
}
water1
Description
Input
解题思路:
水题。找一个最高点h,答案就是(h+1)*sum(wi) - 各海拔。
AC代码:
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
typedef long long ll;
int main(){
int n;
while(~scanf("%d",&n)){
if(n == 0){
printf("1\n");
continue;
}
ll maxh = 0,maxl = 0,sum = 0;
ll h,w;
for(int i = 0; i < n; i++){
scanf("%lld%lld",&h,&w);
maxh = max(maxh,h);
sum += h*w;
maxl += w;
}
printf("%lld\n",(maxh+1)*maxl-sum);
}
return 0;
}