NOI元丹:https://www.luogu.org/problemnew/show/P1371
题意概述:在给定的NOI序列中插入一个字符(任选),使得串中含有最多的NOI子序列。
分类讨论。如果插入N,必然是插在最前面好,如果插入I,必然是插在最后面好。这个可以理解吧。
比较麻烦的是插入O。(其实不考虑O这道题也能过,数据水的不可思议),分别讨论每个位置,看前面有几个N,后面有几个I,乘起来即为插入这个O的贡献。
(原来考NOI的秘诀是炼丹啊)
# include <cstdio> # include <iostream> using namespace std; int n; char c[100009]; long long addn() { int N=1,NO=0; long long ans=0; for (int i=1;i<=n;i++) { if(c[i]=='N') N++; if(c[i]=='O') NO+=N; if(c[i]=='I') ans+=NO; } return ans; } long long addi() { int N=0,NO=0; long long ans=0; for (int i=1;i<=n;i++) { if(c[i]=='N') N++; if(c[i]=='O') NO+=N; if(c[i]=='I') ans+=NO; } return ans+NO; } int main() { scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%c",&c[i]); while (c[i]!='N'&&c[i]!='O'&&c[i]!='I') scanf("%c",&c[i]); } long long ans=addn(); ans=max(ans,addi()); cout<<ans; return 0; }
yyy loves Chemistry I:https://www.luogu.org/problemnew/show/P2394
题意概述:输入n,输出n/23(保留8位小数);
因为这个n的精度可能很高,于是就想到了边读入边算边输出。这时候我们发现输出的精度并不是很高....所以也没有必要全部读进来,读上15-6位就足够了,剩下的就不要啦。用long double,输入时是%Lf,注意L是大写。
# include <cstdio> # include <iostream> using namespace std; long double a; int main() { scanf("%20Lf",&a); printf("%.8Lf",a/23.0); return 0; }
好消息,坏消息:https://www.luogu.org/problemnew/show/P2629
题意概述:给定一个数列,从一个断点往后加,期间不能出现负数,再从头加到断点处,期间还是不能有负数。问这样的断点个数。
听说这是单调队列优化dp,一开始想到线段树,ST表。冷静分析一下...不就是...瞎搞吗...
首先求一个前缀和,再对于前缀和数组求一个前缀min,一个后缀min,枚举断点,如果后缀min减去前缀和大于零,后缀和加上前缀min大于零,这个断点就是一个合法的答案,然后就...没啦。
1 # include <cstdio> 2 # include <iostream> 3 # define R register int 4 5 using namespace std; 6 7 const int maxn=1000050; 8 int n,ans=0; 9 int a[maxn],s[maxn],qm[maxn],hm[maxn]; 10 11 int main() 12 { 13 scanf("%d",&n); 14 for (R i=1;i<=n;++i) 15 scanf("%d",&a[i]),s[i]=s[i-1]+a[i]; 16 qm[1]=s[1]; 17 for (R i=2;i<=n;++i) 18 qm[i]=min(qm[i-1],s[i]); 19 hm[n]=s[n]; 20 for (R i=n-1;i>=1;--i) 21 hm[i]=min(hm[i+1],s[i]); 22 if(qm[n]>=0) ans++; 23 for (R i=2;i<=n;++i) 24 { 25 if(hm[i]-s[i-1]<0) continue; 26 if(s[n]-s[i-1]+qm[i-1]<0) continue; 27 ans++; 28 } 29 printf("%d",ans); 30 return 0; 31 }
[PA2014]Iloczyn:https://www.lydsy.com/JudgeOnline/problem.php?id=3713
题意概述:给定一个不大于$1e9$的数字,问它是不是两个斐波那契数的乘积;
这题一看就很数论,然而推了一下发现并不能找出什么结论来,后来写了一个暴力打表找规律,发现不大于$1e9$的斐波那契数非常少,只有$40$多个,所以暴力就行。注意一个小细节:$f[0]=0$,所以$0$是可以乘出来的。
1 # include <cstdio> 2 # include <iostream> 3 4 using namespace std; 5 6 int T; 7 long long x,f[50]; 8 int i; 9 10 int main() 11 { 12 f[0]=0; 13 f[1]=f[2]=1; 14 for (int i=3;i<=45;++i) 15 f[i]=f[i-1]+f[i-2]; 16 scanf("%d",&T); 17 while (T--) 18 { 19 scanf("%lld",&x); 20 bool F=false; 21 for (int i=0;i<=45;++i) 22 for (int j=0;j<=45;++j) 23 if(f[i]*f[j]==x) F=true; 24 if(F) 25 printf("TAK "); 26 else 27 printf("NIE "); 28 } 29 return 0; 30 }
解方程:https://www.luogu.org/problemnew/show/P2312
题意概述:求一个$n$次方程在$[1,m]$,范围内的整数解。$n<=100,m<=1e6,a_i<=10^{1000}$
首先可以想到一个小数据下的做法:枚举每个$x$,代入试一试,只能得30分。然后就是瞎搞时间了:一个普通方程可以认为是一个对于无限大取模的同余方程,所以也可以把无限大变小,尝试一下在模某些大数情况下方程是否成立,如果成立,那很可能在模无限的意义下也成立,建议取一个大一点的质数以提高正确率,也可以多选几个,但是容易超时。(如何看待NOIP出现正解像骗分的题目)。
1 // luogu-judger-enable-o2 2 # include <cstdio> 3 # include <iostream> 4 # include <string> 5 # include <cstring> 6 # define mod 998244353 7 # define R register int 8 9 int n,m; 10 long long a[109]; 11 int ans[1000009],cnt; 12 std::string s; 13 14 inline bool check (int x) 15 { 16 long long ans=0,s=1; 17 for (int i=0;i<=n;++i) 18 { 19 ans=(ans+s*a[i]+mod)%mod; 20 s=(s*x+mod)%mod; 21 } 22 if(ans==0) return true; 23 return false; 24 } 25 26 inline long long read() 27 { 28 int f=1; 29 long long x=0; 30 char c=getchar(); 31 while (!isdigit(c)) 32 { 33 if(c=='-') f=-f; 34 c=getchar(); 35 } 36 while (isdigit(c)) 37 { 38 x=(x*10+c-'0')%mod; 39 c=getchar(); 40 } 41 return x*f; 42 } 43 44 int main() 45 { 46 scanf("%d%d",&n,&m); 47 for (R i=0;i<=n;++i) 48 a[i]=read(); 49 for (R i=1;i<=m;++i) 50 if(check(i)) 51 ans[++cnt]=i; 52 printf("%d ",cnt); 53 for (R i=1;i<=cnt;++i) 54 printf("%d ",ans[i]); 55 return 0; 56 }
找爸爸:无;
听名字就像胡策题...这是高二学长们胡策的T1,感觉非常有趣.
题意概述:给出一棵$n$个节点的树,$q$个询问,每次询问$a$号点的$b$级祖先.$n<=10^7,q<=10^6$
题出的好!覆盖知识点广,题目有着切合实际的背景,解法比较自然。给出题人点赞!
明天再补吧。
---shzr