注意:大部分题目都是我自己主观的代码,很多没有参考题解,但是都是AC的,我喜欢自己做,不到万不得已别去看谢大题解,因为脑袋疼,因此别抱怨不按题解来写文章。
另外,写oj如果是WA那么先观察是不是cin和scanf混用,oj不能混用,如果是TLE而且时间复杂度已经很低了,那么检查一下是不是用了cin没有关闭同步,我建议是用stdio.h然后用sacnf和printf。
1.Candy-1187
样例输入
3 4 5 0
样例输出
1 2 4
题解思路:取模,得到S0,S1,S2,在每个序列中各取三个,然后三个序列每次都取一个,所以SUM=S0取三个+S1取三个+S2取三个+S0*S1*S2;
我的思路:找规律(每次增加的增加多少,建议还是用题解思路做,因为规律我说不清)
AC代码(个人认为难度:2,标准难度:2)
Memory: 11044K | Time: 265MS |
#include
#define mod 1000000007
using namespace std;
long long res[1100000];
int main()
{
res[3]=1;
long long ans=0,temp=1;
long long a[3]={1,2,1};
for(long long i=4;i<=1100000;i++){
if(ans>=3){
for(long long j=0;j<3;j++){
a[j]++;
}
ans=0;
}
res[i]=(res[i-1]+temp)%(mod);
temp+=a[ans++];
}
long long n;
cin>>n;
while(n!=0){
cout<>n;
}
return 0;
}
2.Permutation-1241
3 3 1 2 3 3 2 1 3 3 2 3 1
1 2 3
思路:弄清置换是什么就行,Pn=Pn-1*P1,然后找到每个数到终点位置要置换的次数(因为每个数都会有轮回的,比如第一个数3个轮回就找到了,第二个数4个轮回才找到,那么第12个轮回必然就都会找到),然后求他们最小公倍数;
AC代码(个人认为难度:3,标准难度:2)
Memory: 2448K | Time: 125MS |
#include
#include
#include
using namespace std;
typedef long long ll;
ll lmp(ll a,ll b)//求最大公因数,最大公倍数就等于两数相乘然后除以最大公因数
{
while(a%b!=0){
ll c=a;
a=b;
b=c%b;
}
return b;
}
int main()
{
ll t;
cin>>t;
while(t--){
ll ans=1;
ll n;
cin>>n;
vectorres;
for(ll i=0;i>nums;
res.push_back(nums);
}
for(ll i=0;i
3.RBG-1266
题解思路:
个人思路:贪心,我们先统计RGB有多少个,然后在R的地盘,如果出现G,那么就先跟G区域的R交换,如果G区域没有那么再去B区域交换;如果出现B那么就先去B区域交换,如果没有再返回去G区域交换,就是一句话:尽量换到属于自己的区域就行了。
AC代码(个人难度:2,标准难度:2)
Memory: 2416K | Time: 296MS |
#include
using namespace std;
int main()
{
char s[10001];
while(scanf("%s",s)!=EOF){
long long r=0,g=0,b=0,res=0;
int len=strlen(s);
for(int i=0;i
4.String-1299
AABBCC S 2 4 C T C D END AABBCC T C D S 2 4 C END
1:ACCCCC 2:ADDDDD 1:AABBDD 2:ACCCDD
思路:暴力模拟,水题,注意输入输出就行了。
AC代码(个人难度:1,标准难度:1)
Memory: 2492K | Time: 62MS |
#include
#include
using namespace std;
int main()
{
char s[200];
while(cin>>s){
string res;
int i=0;
while(!(s[0]=='E'&&s[1]=='N'&&s[2]=='D')){
if(res.empty()){
i=0;
res=s;
//cout<>x>>y>>a;
for(int i=x-1;i=res.size()){
break;
}
res[i]=a;
}
cout<>a>>b;
for(int i=0;i>s;
}
cout<
5.Zeros-1301
2 4 2 3 4 5 3 1 3 5
5 Impossible
思路:模拟
AC代码(个人难度:1,标准难度:1)
#include
#include
using namespace std;
bool fun(vector&res)
{
for(int i=0;i>t;
while(t--){
int n;
cin>>n;
vectorres;
for(int i=0;i>nums;
res.push_back(nums);
}
int counts=1;
while(counts++){
if(counts>=1000){
cout<<"Impossible"<
6.折纸-贰-1379
1 1 2
3 4 5
思路:数学,也是水题,不多说。
AC代码(个人难度:1,标准难度:1)
Memory: 2428K | Time: 125MS |
#include
using namespace std;
int lmp(int a,int b)
{
while(a%b!=0){
int c=a;
a=b;
b=c%b;
}
return b;
}
int main()
{
int t;
cin>>t;
while(t--){
int p,q;
cin>>p>>q;
int a=p*q+p*p;
int b=q*q;
int c=p*q+q*q-p*p;
int temp=lmp(a,b);
int res=lmp(temp,c);
cout<
7.大佬带带我-1384
5 3 10 3 10 4 15 1 1 2 5 3 1 2 3 4 1 5
1 0 2 1 0
1号,按能力值可以带2和4号,但是他不喜欢2号,所以只能带4号1个人。 2号,能力值最低,不能带任何人,所以是0个。 3号,按能力值可以带2和4号,他没有不喜欢谁,2和4号也都没有不喜欢他,所以他可以带2个人。 4号,按能力值可以带2号,两者没有不喜欢关系,所以4号可以带1个。 5号,按能力可以带1,2,3,4号,但是他不喜欢1,2,3号,4号又不喜欢他,所以他不能带任何人。
思路:暴力模拟,用结构体保存人物的id和能力值it,然后排序;
然后保存相互讨厌的人,在遍历的时候过滤掉就行,
难点在于如何保存相互讨厌的人,我的办法是用二维容器,然后再遍历的时候作标记(题目真恶心)。
AC代码(个人难度:4,标准难度:4)
Memory: 8368K | Time: 1685MS |
#include
#include
#include
#include
using namespace std;
typedef long long ll;
vectorans[10001];//二维数组表示不喜欢的人
int ch[10001];//结果
struct node
{
int id;
int it;
}res[10001];
int cmp(node a,node b)
{
if(a.it!=b.it){
return a.it
8.面积-1385
2 1 2 1 1 1 3 1 3
0 5/18
思路:数学,然后再注意一下特殊情况就行了。
AC代码(个人难度:1,题解难度:1)
Memory: 2424K | Time: 15MS |
#include
using namespace std;
typedef long long ll;
ll lmp(ll a,ll b)
{
while(a%b!=0){
ll c=a;
a=b;
b=c%b;
}
return b;
}
int main()
{
ll t;
cin>>t;
while(t--){
ll a,b,c,d;
cin>>a>>b>>c>>d;
ll n=a*d+c*b+d*b-c*b+a*c;
ll m=2*d*b;
ll temp=lmp(n,m);
n/=temp;
m/=temp;
if(m-n==0){
cout<<0<
9.彩球-1386
2 5 1 2 3 2 1 5 1 2 1 2 1
4 0
思路:还是按谢大的来,要熟练地用哈希表或者map,我本以为这个题目两重循环已经够快了,是真的没想到只要在三种里面去掉一种和两种就行了。我是笨比。另外还有一种递推解法(肖大佬的解法),简单来说取三种可以由取两种得到,而取两种又能由取一种得到。很久没这样想了我也懒得写。就按原始的来吧,注意用c的一定要用stdio.h和scanf,不然必定超时。
AC代码(个人难度:4,题解难度:3)
#include
#include
#include
#include
using namespace std;
typedef long long ll;
int main()
{
ll t;
scanf("%lld",&t);
while(t--){
unordered_mapa;
ll n;
scanf("%lld",&n);
ll res[10001];
memset(res,0,sizeof(res));
for(ll i=0;isecond;
if(y==2){
sum-=n-2;//减去两种相同的
}
else if(y>=3){
sum-=y*(y-1)*(y-2)/6;//减去三种相同的
sum-=y*(y-1)/2*(n-y);//减去三种里面两种相同的
}
}
printf("%lld\n",sum);
}
return 0;
}
10.完全区间-1387
我以前的博客有,可以去翻我以前的题解。
11.菱形-1403
1 2 3 4 5 6 7 0
/\ \/ /\ /\/ \/ /\ /\/\ \/\/ /\ /\/\ \/\/ \/ /\ /\/\ /\/\/ \/\/ /\ /\/\ /\/\/\ \/\/\/ /\ /\/\ /\/\/\ \/\/\/ \/
思路:我觉得挺简单的,不知道为什么很多人拿二维数组算来算去。
我们先来考虑上部分,是由“/\”和“/”组成
下部分仅仅只有“\/”组成。
那么就很简单了,上一部分每一行应该打印的个数就是行数,比如第一行就一个菱形,第二行两个菱形......如果上一部分某行菱形个数不足行数,那么就多打印“/”就行,其他全都是“/\”;
下一部分就别管了,有多少就打印多少“\/”。
AC代码(个人难度:2,标准难度:3)
Memory: 2388K | Time: 15MS |
#include
using namespace std;
int main()
{
int n;
int left[21],right[21];
for(int i=1;i<=20;i++){
left[i]=(i-1)*(i-1)+1;
right[i]=i*i;
}
cin>>n;
while(n!=0){//先由公式推出边长m
int m=0;
for(int i=1;i<=21;i++){
if(n>=left[i]&&n<=right[i]){
m=i;
break;
}
}
int nums=n;
for(int i=1;i<=m;i++){
for(int j=0;j=i){//如果一行够这么多,就只打印“/\”
for(int j=0;j=1;i--){
if(nums<=0){
break;
}
for(int j=0;j=i){
for(int j=0;j>n;
}
return 0;
}
12-菱形2-1404
2 2 1 3 3 1 7
1 3
题解思路:菱形转过45°是正方形,相当于求这个正方形两点最短距离,这个找到坐标即可,因此找到对应的坐标才是难点。
我的思路:直接当做菱形看,找到坐标,左边left距离为abs(y1-x1+x0-y0),右边right距离为abs(x1+y1-x0-y0),目标距离为(left+right)/2,证明我会在有空的时候给出。
AC代码(个人难度:4,标准难度:3)
Memory: 1432K | Time: 906MS |
#include
#include
#include
using namespace std;
typedef long long ll;
int main()
{
ll t;
scanf("%lld",&t);
while(t--){
ll n,s,e;
scanf("%lld%lld%lld",&n,&s,&e);
if(s>e){//一定要是一上一下的排序
ll temp=s;
s=e;
e=temp;
}
ll x=0,y=1,b[4];//b的四个数组表示两个点的坐标。
int sign=0,flag=0;
for(ll i=0;i<2*n-1;i++){//直接看做菱形坐标,啥也不管
x+=y;
//printf("%lld ",x);
y--;
if(x>=s&&sign==0){
sign=1;
b[0]=y-(x-s)*2;
b[1]=i;
}
if(x>=e&&flag==0){
flag=1;
b[2]=y-(x-e)*2;
b[3]=i;
break;
}
y++;
if(i
13.世界杯-1405
2 2 1.3 4.8 10.5 1.4 4.0 9.7 2 1.3 5.6 9.8 1.45 5.0 8.9
No Yes
思路:想到了就很简单,本金/赔率=亏本息,因此只要本息>本金即可。所以我们三个状态都得买,只要存在某三个状态使得亏本息<本金那么一定能赚。
AC代码(个人难度:2,标准难度:2)
Memory: 2444K | Time: 202MS |
#include
#define maxn 1000
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
int n;
cin>>n;
double res[15][3];
for(int i=0;i>res[i][0];
cin>>res[i][1];
cin>>res[i][2];
}
double s=0,x=1;//x表示本金
int flag=0;
for(int i=0;i
14.String Game-1406
4 6 2 xxxttu xxttuu 6 5 xxxttu xxttuu 6 3 xtuxtu xxttuu 4 0 alic ebob
Alice Draw Draw Bob
思路:这是一个思维题,考虑特殊情况即可,另外,举个例子,xxxu,三回合,它也能变成xxxx。当xxxx,一回合,那么只能减少1;
AC代码(个人难度:3,标准难度:3)
Memory: 2296K | Time: 265MS |
#include
#include
#include
using namespace std;
typedef long long ll;
templateinline void read( t &res){
char c;t flag=1;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}
int main()
{
ll t;
read(t);
while(t--){
ll n,m;
ll a[30],b[30];
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
read(n);//快读,用scanf也行
read(m);
ll count0=0,count1=0;
char s[101],st[101];
gets(s);
gets(st);
for(ll i=0;icount0){
count0=a[s[i]-'a'];
}
b[st[i]-'a']++;
if(b[st[i]-'a']>count1){
count1=b[st[i]-'a'];
}
}
ll res0=0,res1=0;
if(count0==n){
if(m==1){//特殊情况
res0=n-1;
}
else{
res0=n;
}
}
else if(m>=n-count0){//剩余长度大于回合数的
res0=n;
}
else{
res0=m+count0;//剩余长度小于回合数的
}
if(count1==n){
if(m==1){
res1=n-1;
}
else{
res1=n;
}
}
else if(m>=n-count1){
res1=n;
}
else{
res1=m+count1;
}
if(res0==res1){
printf("Draw\n");
}
else if(res0>res1){
printf("Alice\n");
}
else{
printf("Bob\n");
}
}
return 0;
}
15.Min Base II-1411
5 0 1 4 5 1000000000000000000
2 2 3 3 44
思路:模拟,在此说明一下,如果数据不超过int,你可以用itoa或者bitsize函数来做。
AC代码(个人难度:2,标准难度:2)
Memory: 2424K | Time: 30MS |
#include
#include
#include
#include
using namespace std;
typedef long long ll;
int main()
{
ll t;
cin >> t;
while (t--) {
ll n;
cin >> n;
if (n == 0 || n == 1) {
cout << 2 << endl;
}
for (int i = 2;i <= n;i++) {
ll m = n;
ll flag = 0;
ll s[101];
memset(s, 0, sizeof(s));
while (m != 0) {//进制转换
s[m%i]++;
m /= i;
}
ll nums = 0;
for (int j = 0;j <46;j++) {//找到不属于0的点,最高循环是44,防止溢出你可以多来几次循环,不影响
if (s[j] != 0) {
nums = s[j];
break;
}
}
for (int j = 0;j < 46;j++) {
if (s[j] != 0 && s[j] != nums) {
flag = 1;
break;
}
}
if (flag == 0) {
cout << i << endl;
break;
}
}
}
return 0;
}
16.Rotate Again-1412
2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1 1 2 2 3 3 4 4 2 2 1 1 4 4 3 3
56 15
第一个样例,逆时钟旋转1格,得到最大子矩阵为
11 16 14 15
第二个样例,逆时钟旋转5格,得到最大子矩阵为
3 4 4 4
思路:模拟,没啥说的。将矩阵外部用数组保存起来,然后一直轮换即可,注意循环条件
AC代码(个人难度:2,标准难度:2)
Memory: 2412K | Time: 61MS |
#include
#include
#include
using namespace std;
int ch[4][4];
int a[12];
void nums(int *res)//求各个相加的值
{
res[0]=a[11]+a[0]+a[1]+ch[1][1];
res[1]=a[1]+a[2]+ch[1][1]+ch[1][2];
res[2]=a[2]+a[3]+a[4]+ch[1][2];
res[3]=a[4]+a[5]+ch[1][2]+ch[2][2];
res[4]=a[5]+a[6]+a[7]+ch[2][2];
res[5]=a[10]+a[11]+ch[2][1]+ch[2][2];
res[6]=a[8]+a[9]+a[10]+ch[2][1];
res[7]=a[7]+a[8]+ch[1][1]+ch[2][1];
res[8]=ch[1][1]+ch[1][2]+ch[2][1]+ch[2][2];
}
void change()//转
{
int temp=a[0];
for(int i=0;i<12;i++){
if(i!=11){
a[i]=a[i+1];
}
else{
a[i]=temp;
}
}
}
int main()
{
int t;
cin>>t;
while(t--){
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
cin>>ch[i][j];
}
}
memset(a,0,sizeof(a));//-----外围数字-----//
a[0]=ch[0][0];
a[1]=ch[0][1];
a[2]=ch[0][2];
a[3]=ch[0][3];
a[4]=ch[1][3];
a[5]=ch[2][3];
a[6]=ch[3][3];
a[7]=ch[3][2];
a[8]=ch[3][1];
a[9]=ch[3][0];
a[10]=ch[2][0];
a[11]=ch[1][0]; //-----外围数字-----//
int res[9];
memset(res,0,sizeof(res));
nums(res);
int maxs=*max_element(res,res+9);//初始最大值,因为有9个子矩阵
for(int i=0;i<15;i++){
change();
nums(res);
int x=*max_element(res,res+9);
maxs=max(maxs,x);
}
cout<
17.Sum of Sequence-1415
2 4 10 2 5 7 1 6 10 11 2 20 6 8 7
15 14
第一个样例分成2,5和7,1,结果为 7+8 = 15。 第二个样例分成11,2,20,6和8,7,结果为9+5 = 14。
思路:一个典型的前缀和问题,S2=SUM-S1,我们在输入的时候顺便把数组更新为前缀和,然后再遍历一次求余数即可。
AC代码(个人难度:2,标准难度:2)
Memory: 1832K | Time: 1093MS |
#include
#include
#include
using namespace std;
typedef long long ll;
ll res[50001];
int main()
{
ll t;
scanf("%lld",&t);
while(t--){
ll n,p;
scanf("%lld%lld",&n,&p);
ll sum=0;//最后的总和
memset(res,0,sizeof(res));
for(ll i=0;i0){
res[i]+=res[i-1];
}
}
ll maxs=0;
for(ll i=n-1;i>=0;i--){//前缀和
//printf("%lld ",(sum-res[i])%p+res[i]%p);
if(maxs<((sum-res[i])%p+res[i]%p)){
maxs=(sum-res[i])%p+res[i]%p;
}
}
printf("%lld\n",maxs);
}
return 0;
}
但是不知道为什么不知道是数据问题还是题目问题,我第一次没有用前缀和也能过,希望有大佬能够指出,贴:
#include
#include
#include
using namespace std;
typedef long long ll;
ll res[50001];
int main()
{
ll t;
scanf("%lld",&t);
while(t--){
ll n,p;
scanf("%lld%lld",&n,&p);
ll sum=0;
memset(res,0,sizeof(res));
for(ll i=0;i=0;i--){
//printf("%lld ",(sum-res[i])%p+res[i]%p);//没用前缀和直接一个比
if(maxs<((sum-res[i])%p+res[i]%p)){
maxs=(sum-res[i])%p+res[i]%p;
}
}
printf("%lld\n",maxs);
}
return 0;
}
18.黄金十字-1420
2 3 3 1 1 1 2 2 2 3 3 3 4 4 1 1 1 1 1 2 3 4 4 3 2 1 1 1 1 1
10 15
第一个样例,只有一个中心点在(2,2)的十字可以选择,所以是10。
第二个样例,中心点在(2,2)或(3,3)的十字是答案,为15。
思路:模拟,算出每个行和列的总和,然后相加,再去掉中间重复的点
AC代码(个人难度:2,标准难度:2)
Memory: 2340K | Time: 888MS |
#include
#include
#include
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d%d",&n,&m);
int ch[100][100];
for(int i=0;i
19.Dice I-1420
UDLRXY LUUDD UULDD
1 4 3
思路:模拟,用一个6数组保存六个面,然后根据各个指令进行操作即可。
AC代码(个人难度:2,标准难度:2)
Memory: 2336K | Time: 45MS |
#include
#include
using namespace std;
int main()
{
char s[201];
while(scanf("%s",s)!=EOF){
int a[6]={2,1,5,6,3,4};
//printf("%d",strlen(s));
for(int i=0;i=0;i--){
if(i==0){
a[i]=temp;
}
else{
a[i]=a[i-1];
}
}
}
else if(s[i]=='L'){
int temp=a[1];
a[1]=a[5];
a[5]=a[3];
a[3]=a[4];
a[4]=temp;
}
else if(s[i]=='R'){
int temp=a[1];
a[1]=a[4];
a[4]=a[3];
a[3]=a[5];
a[5]=temp;
}
else if(s[i]=='X'){
int temp=a[0];
a[0]=a[4];
a[4]=a[2];
a[2]=a[5];
a[5]=temp;
}
else{
int temp=a[0];
a[0]=a[5];
a[5]=a[2];
a[2]=a[4];
a[4]=temp;
}
/*for(int i=0;i<6;i++){
printf("%d ",a[i]);
}*/
}
printf("%d\n",a[1]);
}
return 0;
}
20.Dice-1426
2 1 2 3 4 5 6 0 1 2 3 4 5 4 5 6 7 8 9 1 2 3 4 5 6 0 1 2 7 8 9 3 4 5 6 7 8
720 810
思路:直接暴力set容器,注意一位数二位数三位数都是满足条件的,不会set的可以用三维数组做。
AC代码(个人难度:2,标准难度:2)
Memory: 2244K | Time: 328MS |
#include
#include
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--){
setres;
int a[6],b[6],c[6];
for(int i=0;i<6;i++){
scanf("%d",&a[i]);
res.insert(a[i]);//一位数
}
for(int i=0;i<6;i++){
scanf("%d",&b[i]);
res.insert(b[i]);//一位数
}
for(int i=0;i<6;i++){
scanf("%d",&c[i]);
res.insert(c[i]);//一位数
}
for(int i=0;i<6;i++){
for(int j=0;j<6;j++){
for(int k=0;k<6;k++){//三位数
res.insert(a[i]*100+b[j]*10+c[k]);
res.insert(a[i]*100+c[j]*10+b[k]);
res.insert(b[i]*100+a[j]*10+c[k]);
res.insert(b[i]*100+c[j]*10+a[k]);
res.insert(c[i]*100+b[j]*10+a[k]);
res.insert(c[i]*100+a[j]*10+b[k]);
}
}
}
for(int i=0;i<6;i++){
for(int j=0;j<6;j++){//二位数
res.insert(a[i]*10+b[j]);
res.insert(a[j]*10+b[i]);
res.insert(a[i]*10+c[j]);
res.insert(a[j]*10+c[i]);
res.insert(b[i]*10+a[j]);
res.insert(b[j]*10+c[i]);
res.insert(b[i]*10+c[j]);
res.insert(b[j]*10+a[i]);
res.insert(c[i]*10+a[j]);
res.insert(c[j]*10+b[i]);
res.insert(c[i]*10+b[j]);
res.insert(c[j]*10+b[i]);
}
}
printf("%d\n",res.size());
}
return 0;
}