A:
B:
C: Molly's Chemicals(前缀和+map)
题意:在这个数组里面取连续的一段,问有多少种取法使得这段的和为k的自然数幂次;
思路:不能直接暴力,连续的自然联想到前缀和,假设要求和为x的数目,k的不同的幂次就是多个不同的x的计数和了;sum[i]-sum[j]=x,sum[i]-x=sum[j],累计sum[j]的数目就好了;
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=1e5+10;
int n,k;
LL a[maxn];
vector<LL>ve;
map<LL,int>mp;
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)scanf("%I64d",&a[i]);
LL tep=1;
for(int i=1;i<=60;i++)
{
if(abs(tep)>1e14)break;
ve.push_back(tep);
tep=tep*k;
}
sort(ve.begin(),ve.end());
int len=unique(ve.begin(),ve.end())-ve.begin();
// for(int i=0;i<len;i++)cout<<ve[i]<<endl;
LL ans=0,sum=0;
mp[0]++;
for(int i=1;i<=n;i++)
{
sum=sum+a[i];
for(int j=0;j<len;j++)
{
LL temp=ve[j];
ans=ans+mp[sum-temp];
}
mp[sum]++;
}
cout<<ans;
return 0;
}
D: The Door Problem(2-SAT)
题意:有m个开关和n个门,每个门都是由两个开关控制,但每个开关控制可能不止一个门,现在给出初始的门的开闭状况,问是否有一种方法使所有的门都打开;
思路:由于每个门都是由两个开关控制,所以对于门为1(开)应该只有一个开关变化,对于门为0(闭)两个开关要么都变要么都不变,这就是2-SAT的问题的模型了;
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+4;
int n,m,r[maxn],s[2*maxn],c=0;
vector<int>ve[maxn],G[maxn*2];
bool mark[2*maxn];
bool dfs(int x)
{
if(mark[x^1])return false;
if(mark[x])return true;
mark[x]=true;
s[c++]=x;
for(int i=0;i<G[x].size();i++)
{
if(!dfs(G[x][i]))return false;
}
return true;
}
inline void add(int x,int xval,int y,int yval)
{
x=x*2+xval;
y=y*2+yval;
G[x^1].push_back(y);
G[y^1].push_back(x);
}
bool solve()
{
for(int i=0;i<m*2;i+=2)
{
if(!mark[i]&&!mark[i+1])
{
c=0;
if(dfs(i))
{
while(c>0)mark[s[--c]]=false;
if(!dfs(i+1))return false;
}
else return false;
}
}
return true;
}
int main()
{
memset(mark,0,sizeof(mark));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&r[i]);
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d",&x);
for(int j=1;j<=x;j++)
{
scanf("%d",&y);
ve[y].push_back(i);
}
}
for(int i=1;i<=n;i++)
{
int u=ve[i][0],v=ve[i][1];
if(r[i])add(u,0,v,1),add(u,1,v,0);
else add(u,0,v,0),add(u,1,v,1);
}
if(solve())puts("YES");
else puts("NO");
return 0;
}
E: The Holmes Children(数论)
题意:给出了这个公式,和f(n)和g(n)的公式,求给定的n和k下的函数值;
思路:f(n)是满足x+y=n&&gcd(x,y)==1的(x,y)对数,即gcd(x,n-x)==1的对数,就是欧拉函数值phi(n),g(n)=∑f(n/d)(d|n)=n;Fk(n)等于(k+1)/2层欧拉函数,所以就变成了一道简单题啦;
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL n,k;
const int maxn=1e6+10;
const LL mod=1e9+7;
int vis[maxn],cnt=0;
LL prime[maxn];
inline void init()
{
for(int i=2;i<maxn;i++)
{
if(!vis[i])
{
prime[cnt++]=i;
for(int j=2*i;j<maxn;j+=i)vis[j]=1;
}
}
}
LL phi(LL x)
{
LL tep=x;
for(int i=0;i<cnt;i++)
{
if(x<prime[i])break;
if(x%prime[i]==0)
{
tep=tep/prime[i]*(prime[i]-1);
while(x%prime[i]==0)x/=prime[i];
}
}
if(x>1)tep=tep/x*(x-1);
return tep;
}
LL solve(LL cur,LL num)
{
if(cur==1)return 1;
if(num==0)return cur;
return solve(phi(cur),num-1);
}
int main()
{
init();
cin>>n>>k;
k=(k+1)/2;
cout<<solve(n,k)%mod;
return 0;
}