B 牛牛想起飞
题解
DP问题,dp[i][j]表示前i个数中是否有%m为j的数,有为1,否则为0。
官方题解
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL N = 500010, M = 100;
int dp[N][M],a[N],b[N];
int main()
{
LL n, m, res = 0,sum1 = 0;
scanf("%lld%lld", &n, &m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum1 =(sum1 + a[i]) % m;
}
dp[0][sum1] = 1;
for(int i=1;i<=n;i++)
{
scanf("%d",&b[i]);
dp[i][sum1] = 1;
}
for(int i = 1; i <= n; i++)
{
for(int j = 0; j < m; j++)
{
if(dp[i - 1][j] == 1)
{
dp[i][(j + b[i]) % m] = 1;
dp[i][(j - b[i]) % m] = 1;
dp[i][j] = 1;
}
}
}
for(int j = m - 1; j >= 0;j --)
{
if(dp[n][j] == 1)
{
printf("%d",j);
break;
}
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
using namespace std;
const int N = 1e5 + 5;
int a[N], b[N];
bool dp[N][3][105]; // 不变化 加b[i] 减b[i] %y意义下最大
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int n, y;
cin >> n >> y;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++) cin >> b[i];
memset(dp, false, sizeof(dp));
dp[0][0][0] = true;
for (int i = 1; i <= n; i++) {
for (int k = 0; k < y; k++) {
vector<int> v;
v.emplace_back(0);
v.emplace_back(-b[i]);
v.emplace_back(b[i]);
for (int j = 0; j < 3; j++) {
dp[i][0][k] |= dp[i - 1][j][((k - a[i] - v[0]) % y + y) % y];
dp[i][1][k] |= dp[i - 1][j][((k - a[i] - v[1]) % y + y) % y];
dp[i][2][k] |= dp[i - 1][j][((k - a[i] - v[2]) % y + y) % y];
}
}
}
int ans = 0;
for (int k = 0; k < y; k++) {
for (int j = 0; j < 3; j++) {
if (dp[n][j][k]) {
ans = k;
}
}
}
cout << ans << '\n';
return 0;
}
最小互质数
题解
最小出现且没有出现在给出数的因子的素数即可。
线性筛求因子即可。
注意1的特殊情况
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 100010;
int primes[N], cnt;
int minp[N];
bool st[N];
void get_primes(int n)
{
for (int i = 2; i <= n; i ++ )
{
if (!st[i])
{
minp[i] = i;
primes[cnt ++ ] = i;
}
for (int j = 0; primes[j] * i <= n; j ++ )
{
int t = primes[j] * i;
st[t] = true;
minp[t] = primes[j];
if (i % primes[j] == 0) break;
}
}
}
int h[N * 2];
bool judge(int n)
{
if(n == 1) return 1;
for(int i = 2; i * i <= n; i++)
{
if(n % i == 0)return 0;
}
return 1;
}
int main()
{
get_primes(N - 1);
int x;
int n;
scanf("%d", &n);
int flag = 0;
for(int i = 1; i <= n; i++)
{
scanf("%d", &x);
if(x == 1) flag = 1;
while (x > 1)
{
int p = minp[x];
h[p] = 1;
while (x % p == 0)
{
x /= p;
h[x] = 1;
}
}
}
if(flag == 0)
{
cout<<1<<endl;
return 0;
}
for(int i = 1; ;i++)
{
if(h[i] == 0 && judge(i) == 1)
{
cout<< i<<endl;
break;
}
}
return 0;
}
E 牛牛的反函数
题解
找规律
注意答案不能超过1e18。
y奇数时,最小的x= 2^(y/2)+2,
y偶数时,最小的x=2^(y/2-1)+ 1
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 100010;
int primes[N], cnt;
int minp[N];
bool st[N];
LL dfs(LL n)
{
if(n == 1) return n;
if(n != 1 && n % 2 == 1) return dfs(n + 1) + 1;
return dfs(n/2) + 1;
}
LL qmi(LL a, LL b)
{
LL res = 1;
while (b)
{
if (b & 1) res = res * a;
a = a * (LL)a;
b >>= 1;
}
return res;
}
int main()
{
//cout<<qmi(2,60)<<endl;
/*for(LL i = 1; i <= 100; i++)
{
cout<<"f("<<i<<")="<<dfs(i)<<endl;
}*/
int T;
cin>>T;
while(T--)
{
LL n;
scanf("%lld",&n);
if(n == 1){
cout<<1<<endl;
continue;
}
if(n % 2 == 1)
{
if((n + 1)/2 - 1> 62)
{
printf("-1\n");
}
else
{
LL res = qmi(2, (n + 1)/2 - 1)+2;
if(res > 1e18)
{
res = -1;
}
printf("%lld\n",res);
}
}
else
{
if((n )/2 - 1> 62)
{
printf("-1\n");
}
else
{
LL res = qmi(2, n/2 - 1)+1;
if(res > 1e18)
{
res = -1;
}
printf("%lld\n",res);
}
}
}
return 0;
}
D 衔尾蛇
示例1
输入
复制
1 1 1
输出
复制
8
说明
一条红蛇咬自己,一种方案。
一条蓝蛇咬自己,一种方案。
一条绿蛇咬自己,一种方案。
一条红蛇和一条蓝蛇互相咬对方的尾巴,一种方案。
一条红蛇和一条绿蛇互相咬对方的尾巴,一种方案。
一条绿蛇和一条蓝蛇互相咬对方的尾巴,一种方案。
三条蛇互相咬,红咬绿,绿咬蓝,蓝咬红,一种方案。
三条蛇互相咬,红咬蓝,蓝咬绿,绿咬红,一种方案。
一共8种方案。
示例2
输入
复制
1 0 0
输出
复制
1
说明
一条红蛇咬自己,显然只有这一种方案。
示例3
输入
复制
3 0 0
输出
复制
3
说明
一条红蛇咬自己,一种方案。
两条红蛇互相咬对方的尾巴,为一种方案。
三条红色互相咬,也是一种方案(1咬2的尾巴,2咬3的尾巴,3咬1的尾巴)
题解
dfs暴力,判重方法可以用环形字符串的方式
#include <bits/stdc++.h>
#define ll long long
using namespace std;
map<string,bool> mp;
int a,b,c,ans;
void solve(string s){
if(!mp[s]){
ans++;
int len=s.size();
for(int i=0;i<len;i++){
string p="";
for(int j=i;j<len;j++) p+=s[j];
for(int j=0;j<i;j++) p+=s[j];
mp[p]=1;
}
}
}
void dfs(int x,int y,int z,string s){
if(s.size()) solve(s);
if(x<a) dfs(x+1,y,z,s+'a');
if(y<b) dfs(x,y+1,z,s+'b');
if(z<c) dfs(x,y,z+1,s+'c');
}
int main(){
scanf("%d%d%d",&a,&b,&c);
dfs(0,0,0,"");
printf("%d",ans);
}
#include<bits/stdc++.h>
using namespace std;
set<string>s;
int main(){
int a,b,c,i,j,k,z,cnt=0;;
cin>>a>>b>>c;
int sum=1;
int n=a+b+c;
for(j=1;j<=n;j++){ //枚举长度为j
sum*=3;
for(i=0;i<sum;i++){ //共i种状态
int p=i,ca=0,cb=0,cc=0;
string temp="";
for(k=0;k<j;k++){ //p转为三进制代表状压值
if(p%3==0)temp+='a',ca++;
if(p%3==1)temp+='b',cb++;
if(p%3==2)temp+='c',cc++;
p/=3;
}
if(ca>a||cb>b||cc>c)continue; //判断合法
for(k=0;k<j;k++){ //判重
string ttemp="";
for(z=k;z<k+j;z++){
ttemp+=temp[z%j];
}
if(s.count(ttemp))break;
}
if(k==j){
s.insert(temp);
// Ouroboros->hikari->tairitsu->kou
cnt++;
}
}
}
cout<<cnt;
}
H 牛清楚的裙子!!!
题解
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e7 + 5;
double f[maxn];
int main()
{
for(int i=1;i<=10000000;i++) f[i] = f[i-1] + 1.0/i;
int T; cin>>T;
while(T--)
{
int n; scanf("%d", &n);
double ans = (n-1) * f[n] + f[n] * 10000;
printf("%.7f\n", ans);
}
}