A
题意:
给一个n*m的矩形方格,问能找到多少个①面积为1②有一条边平行x轴或y轴的三角形③每个顶点都在格点上。
我们可以直接推出以下图形
(忽略字体。。。太困了草草写完睡觉)由于感觉会相乘的时候爆掉,写了个快乘;
#includeusing 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< =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#include #include #include using namespace std; vector 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 =k){ int s=0,e=k-1; while(e
E
定义f(x)为x的因数个数,设f(x)=n则不断进行x=n为几次后n=2
直接o(根号n)算出
#includeusing 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#include #include using namespace std; const int maxn=1e5+10; typedef long long ll; int fa[maxn],siz[maxn],num[maxn];//siz为儿子的数量,num为i所在白块内点的数量 vector 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
G
G-eli和字符串
题意:
给一个字符串包含01,问你可以最多将k个0变为1也可以将1变为0求最长子串长度是多少
#includeusing namespace std; typedef long long ll; int mp[30]; string s; int n,k; queue q[100]; int main(){ cin>>n>>k; cin>>s; int ans=0x3f3f3f3f; for(int i=0;i
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#include #include #include 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 =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<
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
最后是个快速幂,我就不说了.
(欧拉定理:当a和n互质时,a^b(modn)=a^(b mod(&n) )&n表示n所含的小于他的质数个数
由于n是质数,则&n=n-1;
所以运算的时候顺便mod(n-1)
;
#include#include #include #include #include #include #include #include #include #include