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