sub1:ans=a*b%c,龟速乘即可。
#include <stdio.h> #include <stdlib.h> unsigned long long a, b, c, d; unsigned long long mul(unsigned long long a,unsigned long long b) { unsigned long long x=0; while(b) { if(b&1)x=(x+a)%c; b>>=1,a=(a+a)%c; } return x; } void _() { scanf("%llu %llu %llu", &a, &b, &c); d = mul(a,b); printf("%llu\n", d); } int main() { freopen("program1.in","r",stdin); freopen("program1.out","w",stdout); _(); _(); _(); _(); _(); _(); _(); _(); _(); _(); }
sub2:发现是一个递推式,每次转移如下:a'=a+2b+c,b'=a+b,c'=a,直接构造3*3的矩阵,进行矩乘即可。
#include<cstdio> #include<cstring> using namespace std; long long n,p; struct mat{ int a[3][3]; mat(){memset(a,0,sizeof a);} void init(){memset(a,0,sizeof a);for(int i=0;i<3;i++)a[i][i]=1;} void prepare() { memset(a,0,sizeof a); a[0][0]=a[0][1]=a[0][2]=a[1][1]=a[2][0]=1,a[1][0]=2; } }; mat operator*(mat a,mat b) { mat c; for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++) c.a[i][j]=(c.a[i][j]+1ll*a.a[i][k]*b.a[k][j])%p; return c; } void _______() { scanf("%lld %lld", &n, &p); mat A,ret; A.prepare(),ret.init(); while(n) { if(n&1)ret=ret*A; A=A*A,n>>=1; } long long a=ret.a[0][0],b=ret.a[0][1],c=ret.a[0][2],d=((a-2*b+c)%p+p)%p; printf("%lld\n", d); } int main() { freopen("program2.in","r",stdin); freopen("program2.out","w",stdout); _______(); _______(); _______(); _______(); _______(); _______(); _______(); _______(); _______(); _______(); return 0; }
sub3:求Σik,其中k∈[0,4],手算求答案即可,这个没写代码,计算器算算即可。
1000000000000001 1000000000000001 2538972135152631808 2538972135152631808 2806098670314569728 2806098670314569728 6570342264898322432 6570342264898322432 10067259324320137216 10067259324320137216
sub4:随机生成n*n(n<=5000)的0/1矩阵,第一问求值为1的格子选2个进行排列的方案数,显然就是x*(x-1)(x为值为1的格子数);第二问是求对于每个值为1的格子,距离它最近的值为0的格子的距离,输出距离和,显然可以bfs多元最短路搜索,复杂度可以O(Tn2),大约5~10s能跑出答案
#include <iostream> using namespace std; const int N = 5000, inf = 0x3F3F3F3F; int n, m, type,dx[4]={0,0,1,-1},dy[4]={1,-1,0,0}; bool mp[N + 11][N + 11],vis[N+11][N+11]; int qx[N*N+11],qy[N*N+11],d[N+11][N+11]; long long ans; int seed; int next_rand(){ static const int P = 1000000007, Q = 83978833, R = 8523467; return seed = ((long long)Q * seed % P * seed + R) % P; } long long count1() { ans = 0LL; for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) if(mp[i][j])ans++; return ans*(ans-1); } long long count2() { ans = 0LL; int qs=0,qe=0; for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(mp[i][j])vis[i][j]=0; else vis[i][j]=1,d[i][j]=0,qx[qe]=i,qy[qe++]=j; while(qs<qe) { int x=qx[qs],y=qy[qs++]; for(int i=0;i<4;i++) { int u=x+dx[i],v=y+dy[i]; if(u<0||u>=n||v<0||v>=m||vis[u][v])continue; vis[u][v]=1,d[u][v]=d[x][y]+1,qx[qe]=u,qy[qe++]=v; ans+=d[u][v]; } } return ans; } int main(){ freopen("program4.in","r",stdin); freopen("program4.out","w",stdout); cin >> seed; for(int i = 0; i < 10; i++){ cin >> n >> m >> type; for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) mp[i][j] = bool((next_rand() % 8) > 0); cout << (type == 1 ? count2() : count1()) <<endl; } return 0; }
sub5:随机生成n*n(n<=5000)的0/1矩阵,求全1矩阵个数。这题的简化版:https://www.cnblogs.com/hfctf0210/p/10852851.html
#include <iostream> const int N = 5011; int n, m,c[N][N],st[N]; bool data[N][N]; long long sum[N]; int seed; int next_rand(){ static const int P = 1000000007, Q = 83978833, R = 8523467; return seed = ((long long)Q * seed % P * seed + R) % P; } void generate_input(){ std::cin >> n >> m; for(int i = 1; i <=n; i++) for(int j =1; j <=m; j++) data[i][j] = bool((next_rand() % 8) > 0); } long long count3(){ long long ret=0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) c[i][j]=data[i][j]?c[i-1][j]+1:0; int top; for(int i=1;i<=n;i++) { st[0]=top=0; for(int j=1;j<=n;j++) if(!c[i][j])st[0]=j,top=0; else{ while(top&&c[i][j]<=c[i][st[top]])top--; st[++top]=j,sum[top]=sum[top-1]+1ll*(j-st[top-1])*c[i][j]; ret+=sum[top]; } } return ret; } int main(){ freopen("program5.in","r",stdin); freopen("program5.out","w",stdout); std::cin >> seed; for(int i = 0; i < 10; i++){ generate_input(); std::cout << count3() << std::endl; } return 0; }
sub6:发现式子还有自然溢出,快速幂/矩阵类显然不行,想到floyd套圈,学习笔记链接:https://www.cnblogs.com/hfctf0210/p/10725670.html,不过要跑300~400s
#include<iostream> using namespace std; typedef unsigned long long ull; ull T,n,a,b,c; ull s,t,tim,tn,tm; int main() { freopen("program6.in","r",stdin); freopen("program6.out","w",stdout); int T=10; while(T--) { cin>>n>>a>>b>>c; s=t=tn=0,tm=2; while(1) { t=(a*t*t+b)%c; tn++; if(s==t)break; if(tn==tm)tn=0,tm<<=1,s=t; } s=t=tim=0; while(tim<tn)t=(a*t*t+b)%c,tim++; tim=1; while(s!=t)s=(a*s*s+b)%c,t=(a*t*t+b)%c,tim++; tm=(n-tim)%tn+1; tim=1; while(tim<=tm)s=(a*s*s+b)%c,tim++; cout<<s<<endl; } }
sub8:把a~g当成7个点,化成图形,发现10张图需要枚举的变量均不超过2个,由于n%mod很小(大约1e6级别),对于需要枚举不超过1个的8张图,直接枚举即可,剩下2张图直接手推/枚举打表即可。
1018333390 993704934 1053807588 1144151985 712062141 530076748 520686243 337499021 820275783 80253986
sub7/9/10:咕了,太菜了不会