7/11
这次的题比上次顺手得多,虽然我思维也没有很好,但是跟其他方面比,我可能还是更喜欢思维+数学>算法>数据结构。
不需要什么知识的小思维对jls来说就是签(%%%
//B找规律||小思维
//https://ac.nowcoder.com/acm/contest/46811/B
//画图即得递推式。
#include
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
#define int ll
#define pb push_back
#define eb emplace_back
#define m_p make_pair
#define mod 998244353
#define mem(a,b) memset(a,b,sizeof a)
#define pii pair
#define inf 0x3f3f3f3f3f3f3f3f
const int N = 3e5 + 50;
void work() {
int n;cin>>n;
int ans=0;
if(n==1)ans=1;
else if(n==2) ans=-1;
else if(n==3) ans=2;
else if(n==4) ans=2;
else if(n==5) ans=3;
else if(n%2==0){
ans=n/2+n/6;
}else{
n--;ans=n/2+n/6+1;
}
cout<> t;
while (t--) {
work();
}
return 0;
}
//C小构造
//https://ac.nowcoder.com/acm/contest/46811/C
//除了1237以外任何数都可以由456相加得到,提前构造456拼拼凑凑即可。
#include
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
#define int ll
#define pb push_back
#define eb emplace_back
#define m_p make_pair
#define mod 998244353
#define mem(a,b) memset(a,b,sizeof a)
#define pii pair
#define inf 0x3f3f3f3f3f3f3f3f
const int N = 3e5 + 50;
void work() {
int n;cin>>n;
if(n==1||n==2||n==3||n==7){
cout<<"-1\n";return;
}
int t=n%4;
if(t==0){
for(int i=1;i
//D小博弈
//https://ac.nowcoder.com/acm/contest/46811/D
//偶数总可以变成奇数,而奇数只可以变成偶。
//1(奇数)为必败态。奇数后手胜,偶数先手胜。
#include
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
#define int ll
#define pb push_back
#define eb emplace_back
#define m_p make_pair
#define mod 998244353
#define mem(a,b) memset(a,b,sizeof a)
#define pii pair
#define inf 0x3f3f3f3f3f3f3f3f
const int N = 3e5 + 50;
void work() {
int n;cin>>n;
if(n%2==1) cout<<"yukari\n";
else cout<<"kou\n";
}
signed main() {
io;
work();
return 0;
}
//E
//https://ac.nowcoder.com/acm/contest/46811/E
//搞搞全等三角形即可。
#include
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
#define int ll
#define pb push_back
#define eb emplace_back
#define m_p make_pair
#define mod 998244353
#define mem(a,b) memset(a,b,sizeof a)
#define pii pair
#define inf 0x3f3f3f3f3f3f3f3f
const int N = 3e5 + 50;
void work() {
double a,b,c,d;
cin>>a>>b>>c>>d;
double dx=(a-c)/2;
double dy=(b-d)/2;
double x=(a+c)/2-dy;
double y=(b+d)/2+dx;
if(abs(x-(int)x)<1e-5&&abs(y-(int)y)<1e-5)
cout<<(int)x<<" "<<(int)y<<'\n';
else
cout<<"No Answer!\n";
}
signed main() {
io;
work();
return 0;
}
//G
//https://ac.nowcoder.com/acm/contest/46811/G
//我写的像答辩一样的小小dfs
#include
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
#define int ll
#define pb push_back
#define eb emplace_back
#define m_p make_pair
#define mod 998244353
#define mem(a,b) memset(a,b,sizeof a)
#define pii pair
#define inf 0x3f3f3f3f3f3f3f3f
const int N = 3e5 + 50;
int x=0,num=1,stop;
string s;
int qp(int A,int B,int K){
int ans = 1;
A = A % K;
while (B) {
if (B % 2 == 1)
ans = (ans * A) % K;
B /= 2;
A = (A * A) % K;
}
return ans;
}
void dfs(int cur,int ans,string st,char si){
int res=0;
for(int i=cur;;++i){
if(s[i]=='='){
//cout<='0'&&s[i]<='9'){
res*=10;res+=s[i]-'0';
st+=s[i];
}
else if(s[i]=='?'){
if(si=='+'){
ans+=res;res=0;
}else if(si=='-'){
ans-=res;res=0;
}else if(si=='#'){
ans=qp(ans,ans,res);
res=0;
}
dfs(i+1,ans,st+'+','+');
dfs(i+1,ans,st+'-','-');
if(ans>0){
dfs(i+1,ans,st+'#','#');
}
break;
}
else{
if(si=='+'){
ans+=res;res=0;
}else if(si=='-'){
ans-=res;res=0;
}else if(si=='#'){
ans=qp(ans,ans,res);
res=0;
}
si=s[i];
st+=s[i];
}
}
}
void work() {
cin>>s;
int len=s.length();
for(int i=len-1;i>=0;--i){
if(s[i]=='='){
stop=i;
break;
}
x+=(s[i]-'0')*num;
num*=10;
}
dfs(0,0,"",'+');
cout<<"-1\n";
}
signed main() {
io;
work();
return 0;
}
K-永恒守候的爱恋_2023牛客寒假算法基础集训营3 (nowcoder.com)
数学大礼包!
因子个数=分解质因数的所有指数+1的乘积。所以我们可以知道只有不同的因子个数对答案有贡献,该因子是什么并无影响。
最优构造应该是令不同的因子轮很多遍,每轮只出现一次,可以把出现次数看作一个塔,每一轮就是一层,输入也很友善就是有n个酱紫的层,我们还是可以用差分来计数。
对于每一层中的ans贡献都是比同层之前的加了一个出现过的因子,即在第一层里每加一个数,就有一个“1”变成了“2”,即答案增加之前的二倍,依此类推。
对于不同层间,发生改变不同了,例如从第一层是从1->2,第二层是从2->3,相当于不同层的等比数列求和结果相加,在层与层衔接处我们可以记录下每层的结尾,乘上层的公比即是上层首项,本层首项乘公比的项数-1次方即末项。
- 一些合理性解说:因为我们要最优,那一定是把越多的贡献放到越前使加的次数更多,所以如果当前数在本层出现,那说明当前数一定在之前层都出现过,如果没有出现,那在更上层也不可能出现,即这个塔是金字塔(?,下层至少大于等于上层,所以每一层中变化一定相同,可以证明是严格等比数列。
注意这一切操作都在模意义下进行。
#include
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
#define int ll
#define pb push_back
#define eb emplace_back
#define m_p make_pair
#define mod 1000000007
#define mem(a,b) memset(a,b,sizeof a)
#define pii pair
#define inf 0x3f3f3f3f3f3f3f3f
const int N = 3e5 + 50;
int c[N];
ll qp(ll a,ll b,ll m){
ll ans=1;
while(b){
if(b&1) ans=ans*a%m;
a=a*a%m;
b>>=1;
}
return ans;
}
int inv(int a,int b){
return qp(a,b-2,b);
}
void work() {
int n;cin>>n;
mem(c,0);
for(int i=1;i<=n;++i){
int a;cin>>a;
c[1]++;c[a+1]--; //差分
}
for(int i=1;i<=200005;++i){
c[i]+=c[i-1];
}
int a1=1,last=1;
int q;
int ans=0;
for(int i=1;;++i){
if(c[i]==0) break;
q=(i+1ll)*inv(i,mod)%mod;//公比
a1=last*q%mod; //首项
int res=a1%mod*(qp(q,c[i],mod)-1+mod)%mod*inv((q-1+mod)%mod,mod)%mod;
//其实等比数列求和的分母不需要逆元,他是一定可以整除的,但是写了也无妨
(ans+=res)%=mod;
last=a1*qp(q,c[i]-1,mod)%mod;//末项
}
ans%=mod;
cout<
I-灵魂碎片的收集_2023牛客寒假算法基础集训营3 (nowcoder.com)
好数学的思维,妙妙。
为了便于求和,我们最好令n由少量的素数相乘得到。
从题目中给的特判入手,发现当x为偶数的时候我们可以酱紫构造:如果x-1是素数,令n=(x-1)*(x-1),S(n)=1+x-1=x;如果x-3是素数,令n=2*(x-3),S(n)=1+2+x-3=x。
当x为奇数时,如果n是1个素数那么答案为1,不行。如果n是两个素数乘积,那么我们就要找p,q,令1+p+q=x(x为奇),<=>p+q==x-1,哥德巴赫猜想已经证明在很大很大的范围内对于每一个偶数,我们总可以找到一对奇素数之和等于该偶数,所以只需要枚举就可以辣!
小于7的数要特判一下。
#include
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
#define int ll
#define pb push_back
#define eb emplace_back
#define m_p make_pair
#define mod 998244353
#define mem(a,b) memset(a,b,sizeof a)
#define pii pair
#define inf 0x3f3f3f3f3f3f3f3f
const int N = 1e6 + 50;
int ans[]= {0,-1,-1,4,9,-1,25,8};
bool is[N];
int tot;
int prime[N];
void euler_sieve() {
tot = 0;
is[1]=1;
for (int i = 2; i < N; ++i) {
if (!is[i]) prime[tot++] = i;//0为素数
for (int j = 0; j < tot && prime[j]*i < N; ++j) {
is[prime[j]*i] = 1;
if (i % prime[j] == 0)
break;
}
}
}
void work() {
int x;
cin>>x;
if(x<=7){
cout<> t;
while (t--) {
work();
}
return 0;
}
H-穿越万年的轮回_2023牛客寒假算法基础集训营3 (nowcoder.com)
谔谔,怎么写这题之前还要学学期望dp鸭我有点急。
学了一下,感觉我是不理解这个状态机,这个一个描述状态转移的东西吗?不懂,鸽。
期望dpP4316 绿豆蛙的归宿 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
//反着——反向拓扑
#include
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
#define int ll
#define pb push_back
#define eb emplace_back
#define m_p make_pair
#define mod 998244353
#define mem(a,b) memset(a,b,sizeof a)
#define pii pair
#define inf 0x3f3f3f3f3f3f3f3f
const int N = 2e6 + 50;
int tot = 0;
int head[N];
double f[N];
int du[N], in[N];
int n, m;
struct node {
int nex, to, val;
} arr[N];
void add(int u, int v, int c) {
arr[++tot].nex = head[u];
arr[tot].to = v;
arr[tot].val = c;
head[u] = tot;
}
void topu() {
queueq;
q.push(n);
while (!q.empty()) {
//cout << "111\n";
int t = q.front();
q.pop();
for (int i = head[t]; i; i = arr[i].nex) {
int v = arr[i].to;
f[v] += (f[t] + arr[i].val) / du[v];
//算期望,从v走到u对答案的贡献是(u点贡献+路径长)/从v到u的可能
in[v]--;
//因为是反向建图所以入度减掉
if (!in[v]) {
q.push(v);
}
}
}
//cout << "111\n";
}
void work() {
mem(f, 0);
mem(head, 0);
mem(du, 0);
mem(in, 0);
cin >> n >> m;
for (int i = 1; i <= m; ++i) {
int a, b, c;
cin >> a >> b >> c;
add(b, a, c); //建反图
du[a]++;
in[a]++;
}
f[n] = 0;
topu();
printf("%.2lf\n", f[1]);
}
signed main() {
io;
work();
return 0;
}
//正着——跑dfs
#include
using namespace std;
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
#define int ll
#define pb push_back
#define eb emplace_back
#define m_p make_pair
#define mod 998244353
#define mem(a,b) memset(a,b,sizeof a)
#define pii pair
#define inf 0x3f3f3f3f3f3f3f3f
const int N = 2e6 + 50;
int tot = 0;
int head[N];
double f[N];
int du[N];
bool vis[N];
int n, m;
struct node {
int nex, to, val;
} arr[N];
void add(int u, int v, int c) {
arr[++tot].nex = head[u];
arr[tot].to = v;
arr[tot].val = c;
head[u] = tot;
}
void dfs(int t) {
if (vis[t])
return;
vis[t] = 1;
for (int i = head[t]; i; i = arr[i].nex) {
int v = arr[i].to;
dfs(v); //一定要先递归
f[t] += (f[v] + arr[i].val);
//状态转移的方程是一样的
}
if (du[t]) { //要判断一下是否有度,不然可能出现/0的情况
f[t] /= du[t];
}
}
void work() {
mem(f, 0);
mem(head, 0);
mem(du, 0);
mem(vis, 0);
cin >> n >> m;
for (int i = 1; i <= m; ++i) {
int a, b, c;
cin >> a >> b >> c;
add(a, b, c);
du[a]++;
}
dfs(1);
printf("%.2lf\n", f[1]);
}
signed main() {
io;
work();
return 0;
}
ps:看题解的时候看到了一篇博客,写的时候博主初二,初二是一个还没学期望就已经会了期望dp的年纪,膜膜oi✌别太荒谬。
原来B题正解是二分啊乐,我以为我手绘了那么久的图推出来的规律必然符合数学场的正解,我赛时无法自然地想到并且写对二分,还是乖乖找规律。G我觉得我想的dfs很好,搜的没那么那么爆,但是我写了依托答辩。还有计算几何,虽然这题就是平面几何搞诈骗但是如果真出了寄几的签我是不会写(指没有能力)也不会写(指没有意愿)的。
刚补完,群友锐评质量不佳不如刷刷cf,乐。
jiangly不说话了呜呜难过,想听他超级大脑的巧思,不然我是无法看懂他的代(思)码(维)的。
新年快乐,会幸福。