A题
意思就是给你一个序列a 含有n个元素 和一个数x 然后你需要做的是 在1–x这个段里面减去a序列里面存在的小于等于x 的数 ,求和 大概就是这个意思,很简单
B题 一开始一个序列的值都是相等的 然后他有一种变化值的规则
现在问我们对序列操作若干次后 求和的最大值模1e9+7是多少
emmm这题其实我是推了几个小样例找规律的
其实是程 首项为初始值 公比为2的等比数列分布
求和一次就好了
C题 要你在n个数中找一段连续的数 使得gcd这个段最大 ,然后问你最大值和这个最大的集合有多大 ,显然,因为题目要我们找的是连续的段,而且题面优先保证gcd最大 其次是集合最大 那么我们只需要一开始连续gcd找出来这个最大值 然后再寻找一个连续段的最大长度 都满足a_i%gcdmax =0 即可
D题 给出一个序列a 长度为n 现在要你重新排列使得 数列程这种 分布
问组合的方案数模p 是多少
首先我们要分析,因为他是严格递增或者递减 或者严格递增后再递减
那么显然易得 一个数最多只能出现两次,但是特别的,最大的那个数只能允许出现一次 因为他的峰 显然其他出现两次的数只能放在峰的两边 那么他们对方案数其实是恒定为1的贡献的 我们也不需要计算它的贡献
然后考虑有多少个只出现过一次的的数 首先我们一开始是n个数,通过上述条件判断了否定情况后,峰值一定是一个而且我们不能动它了 那么 n=n-1 然后我们还有cnt个出现次数为2的数 也不能去动它 那么n=n-2*cnt
剩下的数 我们可以随意的分布在左边 若干个 右边若干个
那么相当于是对于组合数求一次 从0 到n(更新后的n) 的组合数值
#include<bits/stdc++.h>
#include<stdlib.h>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define ll long long
#define int long long
#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define IOS ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
ll gcd(ll a,ll b){if(a<0)a=-a;if(b<0)b=-b;return b==0?a:gcd(b,a%b);}
template<typename T>void read(T &res){bool flag=false;char ch;while(!isdigit(ch=getchar()))(ch=='-')&&(flag=true);
for(res=ch-48;isdigit(ch=getchar());res=(res<<1)+(res<<3)+ch - 48);flag&&(res=-res);}
ll lcm(ll a,ll b){return a*b/gcd(a,b);}
ll qp(ll a,ll b,ll mod){ll ans=1;if(b==0){return ans%mod;}while(b){if(b%2==1){b--;ans=ans*a%mod;}a=a*a%mod;b=b/2;}return ans%mod;}//快速幂%
ll qpn(ll a,ll b, ll p){ll ans = 1;a%=p;while(b){if(b&1){ans = (ans*a)%p;--b;}a =(a*a)%p;b >>= 1;}return ans%p;}//逆元 (分子*qp(分母,mod-2,mod))%mod;
ll a[111111];
map<ll,ll>s;
set<ll>sb;
const int Max = 1e6 + 10;
ll fact[Max], ifact[Max]; //fact[i]是i的阶乘,ifact[i]是阶乘的除法逆元,两者用于求组合数
void init() //初始化
{
fact[0] = ifact[0] = 1;
for (int i = 1;i < Max; i++)
{
fact[i] = (fact[i - 1] * i) % mods;
ifact[i] = qp(fact[i], mods - 2,mods);
}
}
ll C(ll n, ll m)
{
if (n < m || m < 0) return 0; //不合法
return (fact[n] * ifact[m] % mods) * ifact[n - m] % mods;
}
signed main(){
init();
ll t;
read(t);
while(t--){
s.clear();
sb.clear();
ll n;
read(n);
ll ma=0;
ll cnt=0;
ll f=0;
for(int i=1;i<=n;i++){
read(a[i]);
// printf("?????\n");
ma=max(ma,a[i]);
s[a[i]]++;
if(s[a[i]]>=3){
f=1;
}
}
for(int i=1;i<=n;i++){
if(s[a[i]]==2){
sb.insert(a[i]);
}
}
if(f||s[ma]>=2){
printf("0\n");
continue;
}
cnt=sb.size();
ll rnm=(n-1)-2*cnt; // 剩余可以自己调用
// printf("%lld\n",rnm);
ll cnm=0;
for(int i=0;i<=rnm;i++){
cnm=(cnm+C(rnm,i))%mods;
}
printf("%lld\n",cnm%mods);
}
return 0;
}
E 题 就是给了我们一个数 和三种情况的价值 三种情况分别对应这个数的因子的种类情况,但是这个因子不能是本身,现在问我们 能求的最小值是多少,三种情况 分别是a b c 值 加上一个X/因子
首先分析 因子为质因子,那么要值尽可能小 我们就要拿它的最大质因子去除,才是此类情况的最小值
然后分析合数因子,一个数如果只有两个质因子相乘组合 那么它没这种情况,否则我们只需要除掉它的 X/min_质因子 也就是它的最大合数因子
还有一种情况就是X本身为质数 我们直接求c+X
综上所述以上三种情况取min 但是x范围1e7 我们需要用到最牛逼的质因子分解才不能TLE (我反正TLE+WA 31发才过)
#include<bits/stdc++.h>
#include<stdlib.h>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define ll long long
#define int long long
#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define IOS ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
/*
const int maxn=1e7+300;
typedef long long LL;
LL v[maxn],primes[maxn];//v[i]存的是i的最小质因子,primes[m]里面存筛出来的质数
LL m=0;//质数数量
void getprimes(int n)
{
//memset(v,0,sizeof(v));//最小质因子
for(LL i=2;i<=n;i++)
{
if(v[i]==0) {v[i]=i;primes[++m]=i;}//i是质数
//给当前的数i乘上一个质因子
for(LL j=1;j<=m;j++)
{
//i有比primes[j]更小的质因子,或者超出n的范围,停止循环
if(primes[j]>v[i]||primes[j]>n/i) break;
//primes[j]是合数i*primes[j]的最小质因子
v[i*primes[j]]=primes[j];
}
}
// for(LL i=1;i<=m;i++) cout<<primes[i]<<endl;
}
*/
bool is_prime(long long x){
if(x==1)
return false;
if(x==2||x==3)
return true;
if(x%6!=1&&x%6!=5)
return false;
int s=sqrt(x);
for(int i=5;i<=s;i+=6)
if(x%i==0||x%(i+2)==0)
return false;
return true;
}
vector<long long> pfc(long long n){//快速质因数分解
vector <long long> st;
long long i=0;
if(n==1)
{
st.push_back(1);
return st;
}
while(i<n)
{
if(is_prime(n)){
st.push_back(n);
return st;
}
for(i=2;i<n;i++)
{
if(n%i==0)
{
st.push_back(i);
n/=i;
break;
}
}
}
st.push_back(n);
return st;
}
vector<ll>sb;
signed main(){
// get_pri();
// getprimes(10000010);
ll t;
scanf("%lld",&t);
while(t--){
ll x;
ll a,b,cc;
scanf("%lld",&x);
scanf("%lld",&a);
scanf("%lld",&b);
scanf("%lld",&cc);
sb=pfc(x);
// for(int i=0;i<sb.size();i++){
// printf("Q %lld\n",sb[i]);
// }
// sb.clear();
ll mafac=sb[sb.size()-1];
ll f=sb[0];
ll ve;
ll ve_;
ll _ve;
if(mafac==x){
printf("%lld\n",cc+x);
continue;
}
// printf("Q %lld %lld\n",mafac,f);
ve=a+x/mafac;
ve_=b+f;
_ve=cc+x;
if(sb.size()==2){
ve_=1111111111;
}
printf("%lld\n",min(min(_ve,ve),ve_));
}
}
F 偷懒 跑路
G 题 给出一个序列a 长度为n
找出一段连续的相乘的值模n等于1的最小长度
是不是很懵逼 ??
我们用map标记
当ai与n不互质时,重置累乘结果以及乘法起点 因为这一段乘法模n不是整除,我们只有当ai与n互质才能往里面加,否则容易形成n 的倍数 显然我们想要获得一段 累乘%n=1 要么这个数%n=1 那么就是一段数的累乘取模结果出现了两次
#include<bits/stdc++.h>
typedef long long ll;
typedef long long LL;
typedef long double ld;
using namespace std;
mt19937_64 mrand(chrono::steady_clock::now().time_since_epoch().count());
//mt19937_64 mrand(42);
#define ii for(int i=1;i<=n;++i)
#define ji for(int j=1;j<=n;++j)
#define jj for(int j=1;j<=m;++j)
#define ij for(int i=1;i<=m;++i)
#define sz(x) ((ll)x.size())
#define all(x) x.begin(),x.end()
#define al(x) x+1,x+1+n
#define asd cout<<"ok"<<endl;
#define asdd cout<<"okok"<<endl;
#define vi vector<int>
#define vvi vector<vector<int>>
#define vl vector<ll>
#define vii vector<pair<int,int>>
#define pr(v) for(auto i:v) cout<<i<<" ";cout<<endl;
#define prt(a, l, r) for(auto i=l;i<=r;++i) cout<<a[i]<<" ";cout<<endl;
#define pc(x) __builtin_popcount(x)
#define pb push_back
#define PS string qqwwee;cin>>qqwwee;
typedef pair<int,int> pii;
const int maxn = 100005;
ll a[maxn],v[maxn];
int gcd(int a,int b) {return b==0?a:gcd(b,a%b);}
void exgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
if(!b) {d=a;x=1;y=0;}
else {exgcd(b,a%b,d,y,x);y-=x*(a/b);}
}
ll inv(ll a,ll p) {
ll d,x,y;
exgcd(a,p,d,x,y);
assert(d == 1);
x%=p;
if(x<0) x+=p;
return x;
}
int main() {
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int t;
cin>>t;
while(t--) {
int n;
cin>>n;
for(int i=1;i<=n;++i) cin>>a[i];
unordered_map<int,int> mp;
mp[1]=0;
int ans=n+1;
ll s=1;
for(int i=1;i<=n;++i) {
if(gcd(a[i],n) != 1) {
s=1;
mp.clear();
mp[1]=i;
} else {
s=s*a[i]%n;
if(mp.count(s)) ans=min(ans,i-mp[s]);
mp[s]=i;
}
}
if(ans>n) ans=0;
cout<<ans<<endl;
}
}