A . 问一组数能否全部被3整除
K. S1 = A, S2 = B, Si = |Si-1 - Si-2|; 一直循环问, 出现了多少不同的数;
多模拟几组数, 可以发现和辗转相除法有很大关系
#include<bits/stdc++.h> using namespace std; #define ll long long ll gcd(ll a, ll b) { ll cnt = 0; // 一开始写的是 int wa 了很多次, 难受 if(b == 0)return 1; cnt += a/b; cnt += gcd(b, a%b); return cnt; } int main() { int T; cin >> T; int j = 0; while(j++ < T) { ll a,b; cin >> a >> b; ll ans ; if(a==0&&b==0) {ans = 1;printf("Case #%d: %lld\n",j,ans);continue;} if((a==0&&b!=0)||(a!=0&&b==0)) {ans = 2;printf("Case #%d: %lld\n",j,ans);continue;} if(a < b) swap(a, b); ans = gcd(a,b); printf("Case #%d: %lld\n",j, ans); } }
F. 给你n朵花, m种颜色, 给花染色,要求正好用到K种颜色,并且相邻的花不能是相同的颜色
写的很详细 : https://blog.youkuaiyun.com/qingshui23/article/details/51125323
首先从m种颜色种选取k种颜色的方案为C(m,k),对于不超过的k种颜色的方案数很好求,为k*(k - 1)^(n - 1),第一个物品有k种选择,之后的n-1个物品因为不能和前
面的相同,故都只有n-1种可能,但是题目要求的是恰好为k种的方案数,因此要容斥一下,容斥可以这样理解,假设不超过i种的方案数为F[i],那么其中包括了不超
过i-1种的,不超过i-1种的里面又包含了不超过i-2种的,以此类推得到ans = F[k] - (F[k - 1] - (F[k - 2] - (... - (F[3] - F[2])))) = F[k] - F[k - 1] + F[k - 2] - ... + (-1)^(k - i)F[i]
因此最后答案为C(m,k)(Σ(-1)^(k - i)F[i]),其中F[i] = C(k,i)i*(i-1)^(n-1)
#include<bits/stdc++.h> #define ull unsigned long long #define ll long long const int mod =1000000007; using namespace std; const int maxn=1e6+5; int t; ll n,m,k; ll exgcd(ll a,ll b,ll &x,ll &y) { if(b==0) { x=1,y=0; return a; } else { ll q=exgcd(b,a%b,y,x); y=y-x*(a/b); return q; } } ll niyuan(ll a,ll n)//逆元 { ll x,y; ll d=exgcd(a,n,x,y); if(d==1) return (x%n+n)%n; else return -1; } ll qmod(ll n,ll m,ll mod)//快速幂 { ll ans=1; while(m) { if(m&1)ans=(ans*n)%mod; n=(n*n)%mod; m>>=1; } return ans%mod; } ll cm[maxn],ck[maxn],inv[maxn]; void get_inv()//打表 { for(int i=1;i<maxn;i++) inv[i]=niyuan(i,mod); } void init()//打表 { cm[0]=1,ck[0]=1; for(int i=1;i<=k;i++) { cm[i]=((cm[i-1]%mod*(m-i+1)%mod)*inv[i])%mod; ck[i]=((ck[i-1]%mod*(k-i+1)%mod)*inv[i])%mod; } } int main() { get_inv(); scanf("%d",&t); int ca=1; while(t--) { scanf("%lld%lld%lld",&n,&m,&k); init(); ll ret; ll ans=0; for(ll i=k; i>=1; i--) { if((k-i)%2) ret=-1; else ret=1; ans=(ans+ret*i%mod*ck[i]%mod*qmod(i-1,n-1,mod)%mod+mod)%mod; //二项式反演 } ans=(ans*cm[k])%mod; printf("Case #%d: %lld\n",ca++,ans); } }