由于本人太蒻了,div1的没有参加,胡乱写了写div2的代码就赶过来了。
T1 苏联人
题目背景
题目名称是吸引你点进来的。
这是一道正常的题,和苏联没有任何关系。
题目描述
你在打 EE Round 1,发现第一题非常无聊。于是你不打了,去下国际象棋了。
结果你发现,由于神秘力量的影响,你的棋子只剩下若干黑色的战车,若干黑色的主教和一只白色的国王了。
由于你很无聊,所以你把一些黑色棋子放在了 8×88 imes 88×8 的棋盘上。
由于你很无聊,所以你想知道,国王放在哪些格子是安全的。换句话说,有哪些格子不会被战车和主教攻击到。当然,国王不能放在已经有棋子的地方。
为了防止你无聊透顶而不知道国际象棋的规则,这里给出以下提示(如果你知道规则那么可以跳过):
国际象棋中,战车可以横向、竖向移动,且格数不受限制。但不能越过其他棋子。
如图,黄色的格子为战车能走到(攻击到)的格子。
国际象棋中,主教可以斜向移动,且格数不受限制。但不能越过其他棋子。
如图,黄色的格子为主教能走到(攻击到)的格子。
简单来说,如果当前位置到目标位置的直线上存在其他棋子,则可以称为“越过了其他棋子”。
如果目标位置是对方的棋子,那么移动到目标位置后,对方的棋子会被吃掉。
更进一步地,你要找的所有位置,必须满足没有黑色棋子能一步走到。
如果你还是没有读懂,可以结合样例进行理解。
输入格式
共 8 行,每行 8 个字符,表示棋盘的状态。
其中 .
表示空位,R
表示战车,B
表示主教。
————————————————————————————————————————————————-
根据题意模拟即可,数据比较水。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int a[9][9]; 4 int main() 5 { 6 for (int i=1;i<=8;i++) 7 for (int j=1;j<=8;j++) 8 { 9 a[i][j]=1; 10 char ch;cin>>ch; 11 if (ch=='B') a[i][j]=3; 12 else if (ch=='R') a[i][j]=2; 13 } 14 for (int i=1;i<=8;i++) 15 for (int j=1;j<=8;j++) 16 { 17 if (a[i][j]==0||a[i][j]==1) continue; 18 if (a[i][j]==2) 19 { 20 for (int k=j-1;k>=1;k--) 21 if (a[i][k]==2||a[i][k]==3) break; 22 else a[i][k]=0; 23 for (int k=j+1;k<=8;k++) 24 if (a[i][k]==2||a[i][k]==3) break; 25 else a[i][k]=0; 26 for (int k=i-1;k>=1;k--) 27 if (a[k][j]==2||a[k][j]==3) break; 28 else a[k][j]=0; 29 for (int k=i+1;k<=8;k++) 30 if (a[k][j]==2||a[k][j]==3) break; 31 else a[k][j]=0; 32 } 33 if (a[i][j]==3) 34 { 35 for (int k=i-1,l=j-1;min(k,l)>=1;k--,l--) 36 if (a[k][l]==2||a[k][l]==3) break; 37 else a[k][l]=0; 38 for (int k=i+1,l=j+1;max(k,l)<=8;k++,l++) 39 if (a[k][l]==2||a[k][l]==3) break; 40 else a[k][l]=0; 41 for (int k=i+1;i+j-k>=1&&k<=8;k++) 42 if (a[k][i+j-k]==2||a[k][i+j-k]==3) break; 43 else a[k][i+j-k]=0; 44 for (int k=i-1;k>=1&&i+j-k<=8;k--) 45 if (a[k][i+j-k]==2||a[k][i+j-k]==3) break; 46 else a[k][i+j-k]=0; 47 } 48 } 49 for (int i=1;i<=8;i++) 50 { 51 for (int j=1;j<=8;j++) 52 if (a[i][j]==1) cout<<1; 53 else cout<<0; 54 cout<<endl; 55 } 56 return 0; 57 }
T2 迫害
题目描述
有 kkk 个人,X 要对这 kkk 个人进行迫害。
这 kkk 个人,每一个人都拥有一个数字,分别从 111 至 kkk。
X 拥有 n+mn+mn+m 个数字,这些数字为 nnn 个 111 和 mmm 个大小可由 X 决定的数字(每个数字定好之后不能更换)。
X 能对这些人进行迫害,当且仅当他能用手中若干个数的加和等于被迫害人的数字,一次迫害就成功了(不会消耗数字)。
由于 X 的权利极大,又十分邪恶,他想要从第 111 个人开始一个一个进行迫害行动。
由于小 Z 也在这个被迫害的行列里,他十分的慌张,希望你来告诉他 X 能最多能从第一个人开始连续迫害多少个人。
由于被迫害的人太多了,所以请将答案对 100000000710000000071000000007 取模。
输入格式
第一行两个整数 n,mn,mn,m,表示 X 有 nnn 个 111,有 mmm 个大小可自定的数。
输出格式
请你告诉小 Z,X 能迫害多少个人。
--------------------------------------------------------------------------------------
可以发现这样的规律:
n=1
1 2 4 8 16……为最佳方案数
n=2
1 1 3 6 12 24……为最佳方案数
归纳得出方案总数为pow(2,m)*(n+1)-1,需要使用快速幂。
1 #include<bits/stdc++.h> 2 #define int unsigned long long 3 using namespace std; 4 int n,m; 5 const int mod=1000000007; 6 unsigned long long qcal(int a, int b) { 7 int ans = 1, base = a; 8 while (b != 0) { 9 if (b & 1 != 0) 10 { 11 ans *= base; 12 ans%=mod; 13 } 14 base *= base; 15 base%=mod; 16 b >>= 1; 17 b%=mod; 18 } 19 return ans%mod; 20 } 21 signed main() 22 { 23 cin>>n>>m; 24 unsigned long long ans=qcal(2,m)*(n+1); 25 ans%=mod; 26 printf("%lld",(ans-1)%mod); 27 return 0; 28 }
T3 代价
题目描述
给出一段序列,删数。代价为a[i-1]*a[i]*a[i+1]。求最小代价。
输入格式
第一行一个正整数 n。
第二行 n 个正整数,第 i个数表示 a[i+1]。
输出格式
一行一个正整数,表示最小的代价和。
-----------------------------------------------------------------------------
贪心比较显然,但关键是怎么贪?
以样例为例:
4
19 26 8 17
序列上实际是1 19 26 8 17 1
既然让代价最小,那我们可以让序列从一端出去,即ans+=a[i]*a[i+1]。因为不管怎样,相邻的两个数必有一乘,乘1能将代价最小化。
但实际上情况要复杂。序列中可能有无穷多个1。按照这种贪心策略,这时候的1是要分开处理的。所以我们不妨将两个1之间的序列单独处理。
具体可以看代码。
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 int ans,a[1000005],minn=0x3f3f3f3f,n,cnt; 5 inline int read() 6 { 7 int x=0,f=1;char ch=getchar(); 8 while(!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();} 9 while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();} 10 return x*f; 11 } 12 signed main() 13 { 14 n=read(); 15 a[0]=a[n+1]=1; 16 for (int i=1;i<=n;i++){ 17 a[i]=read(); 18 minn=min(a[i],minn); 19 } 20 if (minn==1) 21 { 22 minn=0x3f3f3f3f; 23 for (int i=0;i<=n+1;i++) 24 { 25 if (a[i]==1) 26 { 27 ++cnt; 28 if (minn!=0x3f3f3f3f) ans+=minn,minn=0x3f3f3f3f; 29 continue; 30 } 31 minn=min(a[i],minn); 32 if (a[i+1]!=1) ans+=1ll*a[i]*a[i+1]; 33 } 34 ans+=cnt-2; 35 } 36 else{ 37 ans=minn; 38 for (int i=1;i<n;i++) ans+=1ll*a[i]*a[i+1]; 39 } 40 printf("%lld",ans); 41 return 0; 42 }
T4 礼物
-------------------------------------------------------------------------------------------------------
我事先并不知道正解是什么,如果洛谷出题解了,我会仔细看正解的,我的程序很慢很慢。
什么?证明?不存在的!我这种数学蒟蒻怎么会证明!
通过对n<=100的数据进行打表我们可以发现,ans=从1到num所有质数的乘积之和(除了被标记的质数)-1;
(其实是笔者手算了一大堆数据,现在感觉挺秃然的
所以我们现在可以愉快地写代码了。
你会惊奇地发现,全TLE了。
所以这就要考验各位OIer的人品和卡常技巧了。
1.八聚氧
#pragma GCC optimize(3) #pragma GCC target("avx") #pragma GCC optimize("Ofast") #pragma GCC optimize("inline") #pragma GCC optimize("-fgcse") #pragma GCC optimize("-fgcse-lm") #pragma GCC optimize("-fipa-sra") #pragma GCC optimize("-ftree-pre") #pragma GCC optimize("-ftree-vrp") #pragma GCC optimize("-fpeephole2") #pragma GCC optimize("-ffast-math") #pragma GCC optimize("-fsched-spec") #pragma GCC optimize("unroll-loops") #pragma GCC optimize("-falign-jumps") #pragma GCC optimize("-falign-loops") #pragma GCC optimize("-falign-labels") #pragma GCC optimize("-fdevirtualize") #pragma GCC optimize("-fcaller-saves") #pragma GCC optimize("-fcrossjumping") #pragma GCC optimize("-fthread-jumps") #pragma GCC optimize("-funroll-loops") #pragma GCC optimize("-fwhole-program") #pragma GCC optimize("-freorder-blocks") #pragma GCC optimize("-fschedule-insns") #pragma GCC optimize("inline-functions") #pragma GCC optimize("-ftree-tail-merge") #pragma GCC optimize("-fschedule-insns2") #pragma GCC optimize("-fstrict-aliasing") #pragma GCC optimize("-fstrict-overflow") #pragma GCC optimize("-falign-functions") #pragma GCC optimize("-fcse-skip-blocks") #pragma GCC optimize("-fcse-follow-jumps") #pragma GCC optimize("-fsched-interblock") #pragma GCC optimize("-fpartial-inlining") #pragma GCC optimize("no-stack-protector") #pragma GCC optimize("-freorder-functions") #pragma GCC optimize("-findirect-inlining") #pragma GCC optimize("-fhoist-adjacent-loads") #pragma GCC optimize("-frerun-cse-after-loop") #pragma GCC optimize("inline-small-functions") #pragma GCC optimize("-finline-small-functions") #pragma GCC optimize("-ftree-switch-conversion") #pragma GCC optimize("-foptimize-sibling-calls") #pragma GCC optimize("-fexpensive-optimizations") #pragma GCC optimize("-funsafe-loop-optimizations") #pragma GCC optimize("inline-functions-called-once") #pragma GCC optimize("-fdelete-null-pointer-checks")
下面是代码
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<bitset>//压位用的,不然内存会爆炸,笔者用int时内存达到了1G 6 using namespace std; 7 int prime[16252326],num; 8 int n,m,c; 9 int p[25]; 10 bitset<300000010>v; 11 int main() 12 { 13 scanf("%d%d%d",&n,&m,&c); 14 for (register int i=2;i<=n;++i)//您需要灵活优化线性筛素数,才能防止被3e8的数据卡掉 15 { 16 if (!v[i]){ 17 prime[++num]=i; 18 } 19 if((!(i&1))&&(i<<1)<=n){ 20 v[i<<1]=1; 21 continue; 22 } 23 for(register int j=1;j<=num;j+=4){ 24 if(i*prime[j]>n)break; 25 v[i*prime[j]]=1; 26 if(!(i%prime[j]))break; 27 if(j+1>num)break; 28 if(i*prime[j+1]>n)break; 29 v[i*prime[j+1]]=1; 30 if(!(i%prime[j+1]))break; 31 if(j+2>num)break; 32 if(i*prime[j+2]>n)break; 33 v[i*prime[j+2]]=1; 34 if(!(i%prime[j+2]))break; 35 if(j+3>num)break; 36 if(i*prime[j+3]>n)break; 37 v[i*prime[j+3]]=1; 38 if(!(i%prime[j+3]))break; 39 } 40 } 41 for(register int i=1;i<=m;i++){ 42 scanf("%d",&p[i]); 43 if(p[i]==1){//1肯定不行,因为上来就出错,a3=3 44 printf("-1 "); 45 return 0; 46 } 47 } 48 sort(p+1,p+m+1);//这里排序是为了更好地去重 49 int now=1; 50 int ans=1; 51 for(register int i=2;i<=num;++i){ 52 if(now<=m&&p[now]==i){ 53 while(now<=m&&p[now]==i)now++; 54 continue; 55 } 56 ans=(1ll*ans*prime[i])%c; 57 } 58 printf("%d ",(ans-1+c)%c); 59 return 0; 60 }
啊啊啊啊重复一遍我只是个蒟蒻,其实把这个代码发出来是为了给一点思路都没有的同学看的,咱别的不行,OI的基本操作咱还是要会的。
顺带一提,这道题我提交了43次才通过,名副其实的毒瘤题目。