10.16考试总结
A.lgg
1.没有认真理解题意导致 掉了 50 分 (注意关于字符串的题目一定要看看是否问本质不同),根据样例该程序导致掉了 10 分(i == 5)智障,还是要先想好在写,这道题写的极其混乱(只要是涉及到端点和边界的情况,上来就要多出点样例,想清楚)
2.还有变量名称一定要规范,要有一定的意义,当然也不要跟库冲突,这道题我就因为aa和a,ss和s,调了好久,一个优秀的程序设计师不应将这种问题引入程序中
3.debug:的时候,先部分调试,再整体调试,这题,我最后才将小部分的程序找出来错,下次应该早点
code:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
using namespace std;
const long long moda = 1234567891;
const long long modb = 1e9 + 7;
const long long basea = 233;
const long long baseb = 23333;
const int MAXX = 1000100;
long long a[MAXX],b[MAXX],aa[MAXX],bb[MAXX];
int t,n,cnt;
long long record;
char s[MAXX],ss[MAXX];
inline long long getta(int l,int r){
return (aa[r] - (aa[l-1] * a[r - l + 1]) % moda + moda)% moda;
}
inline long long gettb(int l,int r){
return (bb[r] - (bb[l-1] * b[r - l + 1]) % modb + modb) % modb;
}
int main(){
freopen("lgg.in","r",stdin);
freopen("lgg.out","w",stdout);
scanf("%d",&t);
a[0] = 1ll;
for(int i = 1;i <= 1000000;++i)a[i] = a[i-1] * basea % moda;
b[0] = 1ll;
for(int i = 1;i <= 1000000;++i)b[i] = b[i-1] * baseb % modb;
while(t--){
record=0;
cnt = 0;
scanf("%d",&n);
scanf("%s",s+1);
if(!(n & 1)){
printf("NOT POSSIBLE\n");
continue;
}
for(int i = 1;i <= n;++i){
aa[i] = (aa[i - 1] * basea % moda + s[i] - 'a' + 1)%moda;
bb[i] = (bb[i - 1] * baseb % modb + s[i] - 'a' + 1)%modb;
}
int len = ((n - 1) >> 1);
int l1,l2,r1,r2,l,r;
l1 = 1;r2 = n;
for(int i = 1;i <= n;++i){
if(cnt > 1){
printf("NOT UNIQUE\n");
break;
}
if(i == 1){
l1 = i + 1;
r1 = l1 + len - 1;
l2 = r1 + 1;
r2 = n;
if(getta(l1,r1) == getta(l2,r2) && gettb(l1,r1) == gettb(l2,r2)){
if(!record)record = getta(l1,r1);
else if(record)if(record == getta(l1,r1))continue;
for(int j = 1;j <= len;++j)ss[j] = s[l1 + j - 1];
cnt++;
}
continue;
}
if(i == n){
l1 = 1;
r1 = l1 + len - 1;
l2 = r1 + 1;
r2 = n - 1;
if(getta(l1,r1) == getta(l2,r2) && gettb(l1,r1) == gettb(l2,r2)){
if(!record)record = getta(l1,r1);
else if(record)if(record == getta(l1,r1))continue;
for(int j = 1;j <= len;++j)ss[j] = s[l1 + j - 1];
cnt++;
}
if(cnt > 1)break;
continue;
}
if(i <= len){
l1 = 1;r1 = i - 1;
l = i + 1;r = len + 1;
l2 = r + 1;r2 = n;
long long la = ((getta(l1,r1) * a[r - l + 1] ) % moda + getta(l,r)) % moda;
long long lb = ((gettb(l1,r1) * b[r - l + 1] ) % modb + gettb(l,r)) % modb;
if(la == getta(l2,r2) && lb == gettb(l2,r2)){
if(!record)record = getta(l2,r2);
else if(record)if(record == getta(l2,r2))continue;
for(int j = 1;j <= len;++j)ss[j] = s[l2 + j - 1];
cnt++;
}
}else if(i == len + 1){
l1 = 1;r1 = i - 1;
l2 = i + 1;r2 = n;
if(getta(l1,r1) == getta(l2,r2) && gettb(l1,r1) == gettb(l2,r2)){
if(!record)record = getta(l1,r1);
else if(record)if(record == getta(l1,r1))continue;
for(int j = 1;j <= len;++j)ss[j] = s[l1 + j - 1];
cnt++;
}
}else if(i > len + 1){
l1 = 1;r1 = len;
l = len + 1;r = i - 1;
l2 = i + 1;r2 = n;
long long ra = (( getta(l,r) * a[r2 - l2 + 1] ) % moda + getta(l2,r2)) % moda;
long long rb = (( gettb(l,r) * b[r2 - l2 + 1] ) % modb + gettb(l2,r2)) % modb;
if(ra == getta(l1,r1) && rb == gettb(l1,r1)){
if(!record)record = getta(l1,r1);
else if(record){
if(record == getta(l1,r1))continue;
}
for(int j = 1;j <= len;++j)ss[j] = s[l1 + j - 1];
cnt++;
}
}
}
if(cnt == 2)printf("NOT UNIQUE\n");
if(cnt == 1){
for(int i = 1;i <= len;++i)printf("%c",ss[i]);
printf("\n");
}
if(cnt == 0)printf("NOT POSSIBLE\n");
}
fclose(stdin);
fclose(stdout);
return 0;
}
B.biscuits
1.这道题掉了 15 分,没有想到\(A,B\)可能为0,一定要注意边界的数据,尤其是能不能为0,上次牛客就犯过这狗屎错误,还是要长记性
思路:\(A+B\),实质上是将\(A,B\)以一个代价放进盒子,那我们就可以分开考虑\(A,B\)只要他们都\(<=n\)就可以了,还用到了奇技淫巧,倒推阶乘逆元
code:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
using namespace std;
const int MAXX = 1e7+10;
const int mod = 998244353;
int niv[MAXX];
int A, B, n, c = 1, ans;
long long k;
inline int poww(int a,int b){
int ans = 1;
while (b) {
if (b & 1) ans = (long long)ans * a % mod;
a = (long long)a * a % mod;
b >>= 1;
}
return ans ;
}
inline int C(int a){
return (long long)c * niv[a] % mod * niv[n - a ] % mod;
}
int main() {
freopen("biscuits.in","r",stdin);
freopen("biscuits.out","w",stdout);
cin>>n>>A>>B>>k;
if (A == 0 && B == 0) {
int ans = 1ll;
if (k != 0) {
cout<<0<<endl;
return 0;
}
for(int i = 1; i <= n; ++i)ans = (long long)ans * 4ll % mod;
printf("%d\n",ans);
return 0;
}
if (B == 0) swap(A,B);
for (int i = 1; i <= n; ++i)c = (long long)c * i % mod;
niv[n] = poww(c,mod - 2);
for (int i = n - 1;i >= 0; --i)niv[i] = (long long)niv[i + 1] * (i + 1) % mod;
for (int i = 0; i <= n ; ++i){
long long tmp = k - (long long)i * A;
if(tmp < 0)break;
if(tmp % B != 0)continue;
if(tmp / B > n)continue;
ans = (ans + (long long)C(i) % mod * C(tmp / B) % mod) % mod;
}
cout << ans;
return 0;
}