hdu 6322 Problem D. Euler Function
定义一类数,该类数的欧拉函数都是合数,需要求第k大的该类数
打表发现 5 7 8 9 10 11 12 13 。。。。。所以第1大为5 特判一下,之后都是连续的。
#include<bits/stdc++.h>
using namespace std;
long long dp[100010];
vector<int>p[100010];
void dfs(int x,int pre)
{
dp[x]=dp[pre]+1;
for(int i=0;i<p[x].size();i++)
{
if(p[x][i]!=pre)
{
dfs(p[x][i],x);
}
}
}
long long qpow(long long x,long long n,long long mod)
{
long long ans=1;
while(n)
{
if(n&1)ans=ans*x%mod;
x=x*x%mod;
n>>=1;
}
return ans;
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
if(n==1)
{
printf("5\n");
}
else{
printf("%d\n",n+5);
}
}
return 0;
}
hdu 6324 grab the tree
给出一个数,a可以拿走任意一些点,但这些点之间不能存在直接连接的边,另一个人拿剩下的所有点,最后2个人比较自己拿到的点的异或和谁大。
如果所有的数异或和为0,那么假设a拿走的点的异或和为k,那么我们明显能得到另外一个人的异或和必定也为k。所以平局
如果不为0,那么所有的数的异或和的最高位的1一定是由奇数个该位为1的数得到,那么第一个人只要拿1个该最高位为1的数,那么剩下的数的异或和的该最高位则会因为有偶数个1异或而得0,无论如何都不会比第一个人的那个数大。
所以第一个人必胜
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
scanf("%d",&n);
int a;
scanf("%d",&a);
int b;
for(int i=1;i<n;i++)
{
scanf("%d",&b);
a=a^b;
}
int u,v;
for(int i=1;i<=n-1;i++)
{
scanf("%d%d",&u,&v);
}
if(a>0)
printf("Q\n");
else printf("D\n");
}
return 0;
}
hdu 6330 Problem L. Visual Cube
找规律。。。。不算太麻烦的模拟⑧
#include<bits/stdc++.h>
using namespace std;
char ma[88][88];
int main()
{
int t;
cin>>t;
while(t--)
{
int a,b,c;
cin>>a>>b>>c;
for(int i=1;i<=c*2+b*2+1;i++)
{
for(int j=1;j<=a*2+b*2+1;j++)
ma[i][j]='.';
}
for(int i=b*2+1;i<=2*b+1+2*c;i+=2)
{
bool f=1;
for(int j=1;j<=2*a+1;j++)
{
if(f)ma[i][j]='+';
else ma[i][j]='-';
f=!f;
}
}
for(int i=b*2+2;i<=2*b+1+2*c;i+=2)
{
bool f=1;
for(int j=1;j<=2*a+1;j++)
{
if(f)ma[i][j]='|';
else ma[i][j]='.';
f=!f;
}
}
for(int i=1;i<=b*2;i+=2)
{
bool f=1;
for(int j=b*2-i+2;j<=a*2+b*2+1-i+1;j++)
{
if(f)
ma[i][j]='+';
else ma[i][j]='-';
f=!f;
}
}
for(int i=2;i<=b*2;i+=2)
{
bool f=1;
for(int j=b*2-i+2;j<=a*2+b*2+1-i+1;j++)
{
if(f)
ma[i][j]='/';
else ma[i][j]='.';
f=!f;
}
}
for(int i=1;i<=2*b;i+=2)
{
bool f=1;
for(int j=b*2+2-i;j<=2*b+2*c+1-i;j++)
{
if(f)
ma[j][i+2*a+1]='.';
else ma[j][i+2*a+1]='/';
f=!f;
}
}
for(int i=2;i<=2*b;i+=2)
{
bool f=1;
for(int j=b*2+2-i;j<=2*b+2*c+1-i;j++)
{
if(f)
ma[j][i+2*a+1]='|';
else ma[j][i+2*a+1]='+';
f=!f;
}
}
for(int i=1;i<=c*2+b*2+1;i++)
{
for(int j=1;j<=a*2+b*2+1;j++)
cout<<ma[i][j];
cout<<endl;
}
}
return 0;
}
hdu 6319 Problem A. Ascending Rating
单调队列倒着搞一遍,维护一个单调递减队列即可。
每次遍历到一个i,把队尾那些位置超过了i+m-1的数字推掉,再在队头把<=a[i]的数字也推掉,再把a[i]压进队头。
最后队尾为最大值,队列的size为count 。
比赛的时候太菜不会单调队列。现在会了
#include<bits/stdc++.h>
using namespace std;
struct node{
long long da;
long long wz;
}a[11111111];
int main()
{
int t;
cin>>t;
while(t--)
{
long long n,m,k,p,q,r,mod;
scanf("%lld%lld%lld%lld%lld%lld%lld",&n,&m,&k,&p,&q,&r,&mod);
deque<node>qq;
for(int i=1;i<=k;i++)
{
scanf("%lld",&a[i].da);
a[i].wz=i;
}
for(int i=k+1;i<=n;i++)
{
a[i].da=(p*a[i-1].da+q*i+r)%mod;
a[i].wz=i;
}
for(int i=n;i>n-m+1;i--)
{
if(qq.empty())
{
qq.push_back(a[i]);
}
else{
while(!qq.empty()&&qq.front().da<a[i].da)
{
qq.pop_front();
}
qq.push_front(a[i]);
}
}
long long ana=0;
long long anb=0;
for(int i=n-m+1;i>=1;i--)
{
while(!qq.empty()&&qq.back().wz>i+m-1)
{
qq.pop_back();
}
while(!qq.empty()&&qq.front().da<=a[i].da)
{
qq.pop_front();
}
qq.push_front(a[i]);
ana+=qq.back().da^i;
anb+=qq.size()^i;
}
printf("%lld %lld\n",ana,anb);
}
return 0;
}
。。。印象深刻
hdu 6321 Problem C. Dynamic Graph Matching
一道状压dp题。
先解释一下matching ,k=4 则需要挑出4条边,且这四条边无重合点,也就是说这4条边需要8个不同的点来表示。
因为n=10 ,那么我们可以用0~1023来表示我们选了哪些边(在这题我们只需要记录边的数量也就是二进制里1的数量即可不需要记录选了哪些边) dp[i]表示i这个二进制里我们选了数位为1的这些点的答案数。
每次加入一条边 a,b 那么如果某个i的二进制 a--和b--对应位置都为1,那么也就是说这个状态可以由i-(1<<a)-(1<<b)的状态得到,那么就要加上i-(1<<a)-(1<<b)的答案数。以此来累加。
减去一条边,那么我们就反过来减掉即可。
ans[i]表示,选了i个点的答案数,是为了方便输出。题目要求从1~n/2条边,那么对应到点的数量上就是 2 4 6 。。。n-n%2这些下标对应的ans数组的数值。
+1:发现有的人代码能跑2000+ms 我这个码跑了3000+ms ,因为如果i的1的数量为奇数是不需要去更新的。。。
#include<bits/stdc++.h>
using namespace std;
long long dp[1025];
long long ans[1025];
long long cnt[1025];
long long mod=1e9+7;
int main(){
int t;
cin>>t;
for(int i=1;i<=1023;i++)
{
int lss=i;
int js=0;
while(lss)
{
if(lss%2==1)
js++;
lss/=2;
}
cnt[i]=js;
}
while(t--)
{
int n,m;
cin>>n>>m;
memset(dp,0,sizeof(dp));
memset(ans,0,sizeof(ans));
char op[11];
dp[0]=1;
int a,b;
while(m--)
{
scanf("%s%d%d",&op,&a,&b);
a--;
b--;
if(op[0]=='+')
{
for(int i=1;i<(1<<n);i++)
{
if(i&(1<<a)&&i&(1<<b))
{
dp[i]=(dp[i]+dp[i-(1<<a)-(1<<b)])%mod;
ans[cnt[i]]=(ans[cnt[i]]+dp[i-(1<<a)-(1<<b)])%mod;
}
}
}
else{
for(int i=1;i<(1<<n);i++)
{
if(i&(1<<a)&&i&(1<<b))
{
dp[i]=(dp[i]-dp[i-(1<<a)-(1<<b)]+mod)%mod;
ans[cnt[i]]=(ans[cnt[i]]-dp[i-(1<<a)-(1<<b)]+mod)%mod;
}
}
}
int q=0;
for(int i=2;i<=n;i+=2)
{
if(q++)printf(" ");
printf("%lld",ans[i]);
}
printf("\n");
}
}
return 0;
}