A
题意:
给一个n*m的矩形方格,问能找到多少个①面积为1②有一条边平行x轴或y轴的三角形③每个顶点都在格点上。
我们可以直接推出以下图形
(忽略字体。。。太困了草草写完睡觉)由于感觉会相乘的时候爆掉,写了个快乘;
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e5+10; const int mod=1000000007; int n,m,T; string s; int a[maxn]; ll res1,res2,res3,res4; ll mymul(ll a,ll b,ll c) { ll ans=0; a%=c; while(b){ if(b&1) ans=(a+ans)%c; a=(a+a)%c; b>>=1; } return ans%c; } int main() { // cout<<mymul(58212,9702,mod); scanf("%d%d",&n,&m); // if(n<m) swap(n,m); if(n==2&&m==2) printf("0\n"); else { if(n>=2&&m>=3){ res1=mymul(m-2,m-2,mod); res1=mymul(res1,2*n-2,mod); } if(n>=3&&m>=2){ res2=mymul(n-2,n-2,mod); res2=mymul(res2,2*m-2,mod); } if(n>=3&&m>=2){ res3=mymul(m-1,m,mod); res3=mymul(res3,2*n-4,mod); } if(n>=2&&m>=3){ res4=mymul(n-1,n,mod); res4=mymul(res4,2*m-4,mod); } ll res=((((res1+res2)%mod+res3)%mod+res4)%mod); printf("%lld\n",res); } }
c
C-umi和弓道
题意:
umi站在一个位置,还有其他n个靶子在其他位置,你可以在x轴或y轴上放置一堵墙使umi最多只能射中k个靶子,求出墙的最短长度,不能则输出-1
#include<iostream> #include<cmath> #include<vector> #include<algorithm> using namespace std; vector<double> a,b; int main() { double x0,y0,x,y; int n,k; cin>>x0>>y0>>n>>k; k=n-k; for(int i=1;i<=n;i++){ cin>>x>>y; if(x*x0<0) a.push_back(y0-x0*(y-y0)/(x-x0)); if(y*y0<0) b.push_back(x0-y0*(x-x0)/(y-y0)); } double ans=1e18; sort(a.begin(),a.end()); sort(b.begin(),b.end()); if(a.size()>=k){ int s=0,e=k-1; while(e<a.size()){ ans=min(ans,a[e]-a[s]); e++,s++; } } if(b.size()>=k){ int s=0,e=k-1; while(e<b.size()){ ans=min(ans,b[e]-b[s]); e++,s++; } } if(ans==1e18) cout<<-1<<endl; else printf("%.7lf\n",ans); return 0; }
E
定义f(x)为x的因数个数,设f(x)=n则不断进行x=n为几次后n=2
直接o(根号n)算出
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll n; ll get_num(ll n){ ll tot=1; for(ll i=2;i*i<=n;++i){ if(n%i==0){ ll x=0; while(n%i==0){ n/=i; x++; } tot*=(x+1); } } if(n>1)tot*=2; return tot; } int main(){ cin>>n; for(ll i=1;i<=1e12;i++){ n=get_num(n); if(n==2) {printf("%lld\n",i);break;} } }
F-maki和tree
题意:
一颗树中有白色的点与黑色的点,问有多少个点对满足两点连线上只有一个黑色的点
思路:
可以发现,黑点要么在端点要么在两点之间,我们就分这两种情况讨论
在计算之前,我们先将所有只有白色点的连通块利用并查集缩点,sum[i]记录i点所在连通块内白点的个数
①黑点作为端点,那么符合要求的点对就为其所连白点sum[i]的求和
②黑点作为中间点,那么符合要求的点对就为∑∑sum[i]*sum[j](1≤i≤k,i<j≤k) k为其所连白点数
#include<iostream> #include<algorithm> #include<vector> using namespace std; const int maxn=1e5+10; typedef long long ll; int fa[maxn],siz[maxn],num[maxn];//siz为儿子的数量,num为i所在白块内点的数量 vector<ll> a[maxn],temp; char s[maxn]; ll sum[maxn]; int find(ll x) { if(fa[x]==x) return x; return find(fa[x]); } void uni(int x,int y) { int f1=find(x),f2=find(y); if(x!=y){ if(siz[f1]>siz[f2]) fa[f2]=f1,siz[f1]+=siz[f2]+1; else fa[f1]=f2,siz[f2]+=siz[f1]+1; } } ll solve() { if(temp.size()==0) return 0; int n=temp.size(); sum[n]=0; for(int i=n-1;i>=0;i--) sum[i]=sum[i+1]+temp[i]; ll ret=sum[0]; for(int i=0;i<n;i++) ret+=temp[i]*sum[i+1]; return ret; } int main() { int n,x,y; scanf("%lld%s",&n,s+1); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); a[x].push_back(y); a[y].push_back(x); if(s[x]=='W'&&s[y]=='W') uni(x,y); } for(int i=1;i<=n;i++) num[i]=siz[fa[i]]+1; ll ans=0; for(int i=1;i<=n;i++){ if(s[i]=='B'){ for(int j=0;j<a[i].size();j++){ if(s[a[i][j]]=='W') temp.push_back(num[a[i][j]]); } ans+=solve(); temp.clear(); } } cout<<ans<<endl; return 0; }
G
G-eli和字符串
题意:
给一个字符串包含01,问你可以最多将k个0变为1也可以将1变为0求最长子串长度是多少
#include<bits/stdc++.h> using namespace std; typedef long long ll; int mp[30]; string s; int n,k; queue<int>q[100]; int main(){ cin>>n>>k; cin>>s; int ans=0x3f3f3f3f; for(int i=0;i<n;i++){ int tmp=s[i]-'a'; q[tmp].push(i); if(q[tmp].size()==k){ans=min(ans,i-q[tmp].front()+1);q[tmp].pop();} } if(ans==0x3f3f3f3f) puts("-1"); else cout<<ans<<endl; }
I
给一个字符串s,使用其中的nico可得a分,使用niconi可得b分,使用niconiconi可得c分,使用过的不可使用,问最多能得几分
思路:
dp即可
if(i>=3&&s.substr(i-3,4)=="nico") dp[i]=max(dp[i],dp[i-4]+a);
if(i>=5&&s.substr(i-5,6)=="niconi") dp[i]=max(dp[i],dp[i-6]+b);
if(i>=9&&s.substr(i-9,10)=="niconiconi") dp[i]=max(dp[i],dp[i-10]+c);
#include<iostream> #include<cstring> #include<algorithm> #include<string> using namespace std; const int maxn= 3e+5; typedef long long ll; ll dp[maxn]; string s; int main() { int n,a,b,c; scanf("%d%d%d%d",&n,&a,&b,&c); cin>>s; dp[0]=0; for(int i=0;i<n;i++){ if(i>=0) dp[i]=dp[i-1]; if(i>=3&&s.substr(i-3,4)=="nico") dp[i]=max(dp[i],dp[i-4]+a); if(i>=5&&s.substr(i-5,6)=="niconi") dp[i]=max(dp[i],dp[i-6]+b); if(i>=9&&s.substr(i-9,10)=="niconiconi") dp[i]=max(dp[i],dp[i-10]+c); } cout<<dp[n-1]<<endl; return 0; }
J
用到了 矩阵快速幂+欧拉降幂+快速幂
前两项特判就不说了
从第三项开始 都会呈现一定的规律
f( 3) =x1 * y1 * ab
f( 4) =x1 * y2 * a2b
f( 5) =x2 * y3 * a4
f( 6) =x3 * y5 * a7
设 xx yy aa 分别为x y a 的幂
再设g(1)=1 g(2)=1 ,当i>3时 g(i)=g(i-1)+g(i-2)
那么xx=g(n-2) ,yy=g(n-1) aa=g(n)-1 【n>3】
所以我们来一次矩阵快速幂就好了~
但是斐波拉契数列到几十项就快爆了,我们一定要取模,但是怎么取了?
这里用到了欧拉降幂 假如我们要求ab ,现在我们用mod=1e9+7,题目也说了mod是个质数,当a<mod时 a一定与mod互质 可以直接降幂。但当a>=mod时,可能出现a=k*mod的情况,我们要提前特判此时 ab%mod=0 即可(我被这里卡了几个小时)
最后是个快速幂,我就不说了.
(欧拉定理:当a和n互质时,a^b(modn)=a^(b mod(&n) )&n表示n所含的小于他的质数个数
由于n是质数,则&n=n-1;
所以运算的时候顺便mod(n-1)
;
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> #include<stack> #include<queue> #include<vector> #include<set> #include<map> #include<string> #define ls k<<1,l,mid #define rs k<<1|1,mid+1,r #define mp(x,y) make_pair(x,y) #define r(x) read(x) #define rrr(x,y,z) read(x);read(y);read(z) #define FOR(i,l,r) for(int i=l;i<=r;i++) using namespace std; typedef long long LL; typedef pair<int,int> pt; const int N=1e6+5; const int M=2e3+5; const int INF=0x7fffffff; const int mod=1e9+7; const double eps=1e-8; const double pi=acos(-1); LL n,m; struct node { LL f[3][3]; }t; template<class T> inline void read(T &x) { char c; x=1; while((c=getchar())<'0'||c>'9') if(c=='-') x=-1; T res=c-'0'; while((c=getchar())>='0'&&c<='9') res=res*10+c-'0'; x*=res; } node mult(const node &a,const node &b) { node res; FOR(i,1,2) FOR(j,1,2){ res.f[i][j]=0; FOR(k,1,2) res.f[i][j]=(res.f[i][j]+a.f[i][k]*b.f[k][j])%(mod-1); } return res; } LL qpow(LL a,LL p) { LL res=1; while(p){ if(p&1) res=res*a%mod; a=a*a%mod; p>>=1; } return res; } int main() { LL x,y,a,b; rrr(n,x,y); r(a); r(b); x%=mod; y%=mod; a%=mod; b%=(mod-1); if(n==1){cout<<x<<endl; return 0;} else if(n==2){cout<<y<<endl; return 0;} if(x==0||y==0||a==0){cout<<0<<endl; return 0;} LL xx,yy,aa; node now; now.f[1][1]=now.f[2][2]=1; now.f[1][2]=now.f[2][1]=0;//单位矩阵 t.f[1][1]=t.f[1][2]=t.f[2][1]=1; t.f[2][2]=0; //构造出来的矩阵 n-=2; while(n){ if(n&1) now=mult(now,t); t=mult(t,t); n>>=1; } aa=now.f[1][1]+now.f[1][2]; yy=now.f[2][1]+now.f[2][2]; yy=yy%(mod-1); xx=(aa-yy+(mod-1))%(mod-1); aa=(aa-1+(mod-1))%(mod-1); //cout<<xx<<' '<<yy<<' '<<aa<<endl; LL ans=qpow(x,xx)*qpow(y,yy)%mod*qpow(qpow(a,aa)%mod,b)%mod; cout<<ans<<endl; return 0; }
来源:https://www.cnblogs.com/hgangang/p/12267221.html